@applicaster/zapp-react-native-ui-components 13.0.0-alpha.7222542422 → 13.0.0-alpha.7663846546

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 (61) hide show
  1. package/Components/BaseFocusable/index.ios.ts +1 -1
  2. package/Components/BaseFocusable/index.tsx +1 -1
  3. package/Components/Cell/Cell.tsx +7 -4
  4. package/Components/Cell/CellWithFocusable.ios.tsx +126 -0
  5. package/Components/Cell/CellWithFocusable.tsx +43 -59
  6. package/Components/Cell/TvOSCellComponent.tsx +22 -20
  7. package/Components/Cell/__tests__/CellWIthFocusable.test.js +13 -6
  8. package/Components/Cell/index.js +1 -3
  9. package/Components/Focusable/FocusableTvOS.tsx +1 -5
  10. package/Components/Focusable/Touchable.tsx +19 -20
  11. package/Components/FocusableList/index.tsx +9 -25
  12. package/Components/FocusableScrollView/index.tsx +12 -39
  13. package/Components/Layout/TV/NavBarContainer.tsx +7 -8
  14. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +66 -0
  15. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -1
  16. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -11
  17. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/__tests__/index.test.ts +93 -0
  18. package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +1 -1
  19. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  20. package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +2 -2
  21. package/Components/MasterCell/utils/index.ts +1 -1
  22. package/Components/ModalComponent/Header/index.tsx +3 -3
  23. package/Components/River/ComponentsMap/ComponentsMap.tsx +39 -65
  24. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +78 -51
  25. package/Components/River/RiverFooter.tsx +39 -9
  26. package/Components/River/RiverItem.tsx +37 -2
  27. package/Components/River/TV/index.tsx +1 -6
  28. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +100 -31
  29. package/Components/River/__tests__/componentsMap.test.js +17 -5
  30. package/Components/Screen/hooks.ts +56 -0
  31. package/Components/Screen/index.tsx +13 -39
  32. package/Components/Tabs/Tab.tsx +6 -6
  33. package/Components/TextInputTv/index.tsx +2 -2
  34. package/Components/Transitioner/AnimationManager.js +8 -8
  35. package/Components/Transitioner/Scene.tsx +52 -23
  36. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +59 -43
  37. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +2 -2
  38. package/Components/Transitioner/index.js +8 -4
  39. package/Components/VideoLive/LiveImageManager.ts +27 -1
  40. package/Components/VideoLive/PlayerLiveImageComponent.tsx +29 -21
  41. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +51 -1
  42. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +0 -5
  43. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +7 -6
  44. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +2 -3
  45. package/Components/VideoModal/ModalAnimation/utils.ts +2 -2
  46. package/Components/VideoModal/OpaqueLayer.tsx +33 -0
  47. package/Components/VideoModal/PlayerWrapper.tsx +16 -35
  48. package/Components/VideoModal/VideoModal.tsx +14 -23
  49. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -1
  50. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +0 -90
  51. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +89 -0
  52. package/Components/VideoModal/hooks/index.ts +7 -0
  53. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +49 -0
  54. package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +91 -0
  55. package/Components/VideoModal/hooks/utils/index.ts +33 -0
  56. package/Components/VideoModal/utils.ts +1 -1
  57. package/Contexts/ScreenContext/index.tsx +3 -2
  58. package/Decorators/ZappPipesDataConnector/__tests__/Hero.js +1 -1
  59. package/Decorators/ZappPipesDataConnector/index.tsx +31 -1
  60. package/package.json +5 -5
  61. package/Contexts/ComponentsMapOffsetContext/index.tsx +0 -41
@@ -25,7 +25,7 @@ type Props = {
25
25
  };
26
26
 
27
27
  export class BaseFocusable<
28
- T extends Props = Props
28
+ T extends Props = Props,
29
29
  > extends BaseFocusableInterface<T> {
30
30
  constructor(props) {
31
31
  super(props);
@@ -35,7 +35,7 @@ type Props = {
35
35
  };
36
36
 
37
37
  export class BaseFocusable<
38
- T extends Props = Props
38
+ T extends Props = Props,
39
39
  > extends BaseFocusableInterface<T> {
40
40
  constructor(props) {
41
41
  super(props);
@@ -61,7 +61,6 @@ type Props = {
61
61
  skipFocusManagerRegistration?: boolean;
62
62
  shouldUpdate: boolean;
63
63
  behavior: Behavior;
64
- componentsMapOffset: number;
65
64
  };
66
65
 
67
66
  type State = {
@@ -274,10 +273,14 @@ export class CellComponent extends React.Component<Props, State> {
274
273
  if (isFocused) {
275
274
  const accessibilityManager = AccessibilityManager.getInstance();
276
275
 
276
+ const accessibilityTitle =
277
+ item?.extensions?.accessibility?.label || item?.title || "";
278
+
279
+ const accessibilityHint =
280
+ item?.extensions?.accessibility?.hint || "";
281
+
277
282
  accessibilityManager.readText({
278
- text: String(
279
- item.extensions?.accessibility?.label || item.title
280
- ),
283
+ text: `${accessibilityTitle} ${accessibilityHint}`,
281
284
  });
282
285
  }
283
286
 
@@ -0,0 +1,126 @@
1
+ /** TODO: Remove this file when tvos FocusableGroup
2
+ * behaviour is aligned to the web one
3
+ * FocusableGroup should only send onFocus and onBlur events when
4
+ * Focus enters and leaves the Focusables inside the branch
5
+ */
6
+ import * as React from "react";
7
+
8
+ import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
9
+ import * as FOCUS_EVENTS from "@applicaster/zapp-react-native-utils/appUtils/focusManager/events";
10
+ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
11
+ import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
12
+
13
+ import { isAppleTV } from "../../Helpers/Platform";
14
+ import { useCellState } from "../MasterCell/utils";
15
+
16
+ const useCellFocusedState = (
17
+ skipFocusManagerRegistration: boolean,
18
+ groupId: string,
19
+ id: string
20
+ ) => {
21
+ const [currentCellFocused, setCurrentCellFocused] = React.useState(false);
22
+
23
+ React.useEffect(() => {
24
+ const isGroupItemFocused = () => {
25
+ if (!skipFocusManagerRegistration) {
26
+ const isFocused = focusManager.isGroupItemFocused(groupId, id);
27
+ setCurrentCellFocused(isFocused);
28
+ }
29
+ };
30
+
31
+ const handler = () => {
32
+ // tvOS hack for properly checking focus
33
+ if (isAppleTV()) {
34
+ setTimeout(() => {
35
+ isGroupItemFocused();
36
+ }, 0);
37
+ } else {
38
+ isGroupItemFocused();
39
+ }
40
+ };
41
+
42
+ focusManager.on(FOCUS_EVENTS.FOCUS, handler);
43
+
44
+ return () => {
45
+ focusManager.removeHandler(FOCUS_EVENTS.FOCUS, handler);
46
+ };
47
+ }, [groupId, skipFocusManagerRegistration]);
48
+
49
+ return currentCellFocused;
50
+ };
51
+
52
+ type Props = {
53
+ item: ZappEntry;
54
+ CellRenderer: React.FunctionComponent<any>;
55
+ id: string;
56
+ groupId: string;
57
+ onFocus: Function;
58
+ index: number;
59
+ scrollTo: Function;
60
+ preferredFocus?: boolean;
61
+ skipFocusManagerRegistration?: boolean;
62
+ isFocusable?: boolean;
63
+ behavior: Behavior;
64
+ focused?: boolean;
65
+ };
66
+
67
+ export function CellWithFocusable(props: Props) {
68
+ const {
69
+ index,
70
+ item,
71
+ CellRenderer,
72
+ id,
73
+ groupId,
74
+ onFocus,
75
+ scrollTo = noop,
76
+ preferredFocus,
77
+ skipFocusManagerRegistration,
78
+ isFocusable,
79
+ behavior,
80
+ focused,
81
+ } = props;
82
+
83
+ const isFocused = useCellFocusedState(
84
+ skipFocusManagerRegistration,
85
+ groupId,
86
+ id
87
+ );
88
+
89
+ const state = useCellState({
90
+ id: item.id,
91
+ behavior,
92
+ focused: isFocused || toBooleanWithDefaultFalse(focused),
93
+ });
94
+
95
+ const [focusedButtonId, setFocusedButtonId] = React.useState(undefined);
96
+
97
+ // for horizontal scrolling
98
+ React.useEffect(() => {
99
+ if (focusedButtonId) {
100
+ scrollTo(index);
101
+ }
102
+ }, [focusedButtonId]);
103
+
104
+ const handleToggleFocus = (value) => {
105
+ setFocusedButtonId(value.focusedButtonId);
106
+
107
+ if (value.focusable) {
108
+ onFocus(value.focusable, value.mouse);
109
+ }
110
+ };
111
+
112
+ return (
113
+ <CellRenderer
114
+ item={item}
115
+ groupId={groupId}
116
+ onToggleFocus={handleToggleFocus}
117
+ state={state}
118
+ prefixId={id}
119
+ focusedButtonId={focusedButtonId}
120
+ preferredFocus={preferredFocus}
121
+ skipFocusManagerRegistration={skipFocusManagerRegistration}
122
+ isFocusable={isFocusable}
123
+ focused={focused}
124
+ />
125
+ );
126
+ }
@@ -1,48 +1,10 @@
1
1
  import * as React from "react";
2
2
 
3
- import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
4
- import * as FOCUS_EVENTS from "@applicaster/zapp-react-native-utils/appUtils/focusManager/events";
5
3
  import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
6
4
  import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
7
5
 
8
- import { isAppleTV } from "../../Helpers/Platform";
9
6
  import { useCellState } from "../MasterCell/utils";
10
-
11
- const useCellFocusedState = (
12
- skipFocusManagerRegistration: boolean,
13
- groupId: string,
14
- id: string
15
- ) => {
16
- const [currentCellFocused, setCurrentCellFocused] = React.useState(false);
17
-
18
- React.useEffect(() => {
19
- const isGroupItemFocused = () => {
20
- if (!skipFocusManagerRegistration) {
21
- const isFocused = focusManager.isGroupItemFocused(groupId, id);
22
- setCurrentCellFocused(isFocused);
23
- }
24
- };
25
-
26
- const handler = () => {
27
- // tvOS hack for properly checking focus
28
- if (isAppleTV()) {
29
- setTimeout(() => {
30
- isGroupItemFocused();
31
- }, 0);
32
- } else {
33
- isGroupItemFocused();
34
- }
35
- };
36
-
37
- focusManager.on(FOCUS_EVENTS.FOCUS, handler);
38
-
39
- return () => {
40
- focusManager.removeHandler(FOCUS_EVENTS.FOCUS, handler);
41
- };
42
- }, [groupId, skipFocusManagerRegistration]);
43
-
44
- return currentCellFocused;
45
- };
7
+ import { FocusableGroup } from "../FocusableGroup";
46
8
 
47
9
  type Props = {
48
10
  item: ZappEntry;
@@ -75,11 +37,7 @@ export function CellWithFocusable(props: Props) {
75
37
  focused,
76
38
  } = props;
77
39
 
78
- const isFocused = useCellFocusedState(
79
- skipFocusManagerRegistration,
80
- groupId,
81
- id
82
- );
40
+ const [isFocused, setIsFocused] = React.useState(false);
83
41
 
84
42
  const state = useCellState({
85
43
  id: item.id,
@@ -96,26 +54,52 @@ export function CellWithFocusable(props: Props) {
96
54
  }
97
55
  }, [focusedButtonId]);
98
56
 
99
- const handleToggleFocus = (value) => {
100
- setFocusedButtonId(value.focusedButtonId);
57
+ const handleToggleFocus = React.useCallback(
58
+ (value) => {
59
+ setFocusedButtonId(value.focusedButtonId);
60
+
61
+ if (value.focusable) {
62
+ onFocus(value.focusable, value.mouse);
63
+ }
64
+ },
65
+ [onFocus]
66
+ );
67
+
68
+ const onGroupFocus = React.useCallback(() => {
69
+ if (!skipFocusManagerRegistration) {
70
+ setIsFocused(true);
71
+ }
72
+ }, [skipFocusManagerRegistration]);
101
73
 
102
- if (value.focusable) {
103
- onFocus(value.focusable, value.mouse);
74
+ const onGroupBlur = React.useCallback(() => {
75
+ if (!skipFocusManagerRegistration) {
76
+ setIsFocused(false);
104
77
  }
105
- };
78
+ }, [skipFocusManagerRegistration]);
106
79
 
107
80
  return (
108
- <CellRenderer
109
- item={item}
81
+ <FocusableGroup
82
+ id={`focusable-cell-wrapper-${id}`}
83
+ testID={"cell-with-focusable-cell-renderer-focusable-group"}
110
84
  groupId={groupId}
111
- onToggleFocus={handleToggleFocus}
112
- state={state}
113
- prefixId={id}
114
- focusedButtonId={focusedButtonId}
115
85
  preferredFocus={preferredFocus}
116
- skipFocusManagerRegistration={skipFocusManagerRegistration}
117
- isFocusable={isFocusable}
118
- focused={focused}
119
- />
86
+ shouldUsePreferredFocus
87
+ onFocus={onGroupFocus}
88
+ onBlur={onGroupBlur}
89
+ >
90
+ <CellRenderer
91
+ testID={"cell-with-focusable-cell-renderer"}
92
+ item={item}
93
+ groupId={`focusable-cell-wrapper-${id}`}
94
+ onToggleFocus={handleToggleFocus}
95
+ state={state}
96
+ prefixId={id}
97
+ focusedButtonId={focusedButtonId}
98
+ preferredFocus={true}
99
+ skipFocusManagerRegistration={skipFocusManagerRegistration}
100
+ isFocusable={isFocusable}
101
+ focused={focused}
102
+ />
103
+ </FocusableGroup>
120
104
  );
121
105
  }
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import * as R from "ramda";
3
3
  import { View, StyleSheet } from "react-native";
4
4
 
5
- import { Focusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable/FocusableTvOS";
5
+ import { Focusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable";
6
6
  import { FocusableCell } from "@applicaster/zapp-react-native-ui-components/Components/FocusableCell";
7
7
  import { getItemType } from "@applicaster/zapp-react-native-utils/navigationUtils";
8
8
  import { SCREEN_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtils/itemTypes";
@@ -65,7 +65,6 @@ type Props = {
65
65
  isFocusable: boolean;
66
66
  shouldUpdate: boolean;
67
67
  behavior: Behavior;
68
- componentsMapOffset: number;
69
68
  };
70
69
 
71
70
  type State = {
@@ -180,7 +179,6 @@ export class TvOSCellComponent extends React.Component<Props, State> {
180
179
  groupId,
181
180
  component,
182
181
  index,
183
- componentsMapOffset,
184
182
  } = this.props;
185
183
 
186
184
  this.setScreenLayout(componentAnchorPointY, screenLayout);
@@ -195,11 +193,13 @@ export class TvOSCellComponent extends React.Component<Props, State> {
195
193
  const extraAnchorPointYOffset =
196
194
  screenLayout?.extraAnchorPointYOffset || 0;
197
195
 
196
+ const marginTop = screenLayout?.screenMarginTop || 0;
197
+
198
198
  const totalOffset =
199
199
  headerOffset +
200
- (componentAnchorPointY || 0) +
201
- extraAnchorPointYOffset -
202
- componentsMapOffset || 0;
200
+ (componentAnchorPointY || 0) +
201
+ extraAnchorPointYOffset -
202
+ marginTop;
203
203
 
204
204
  mainOffsetUpdater?.(
205
205
  { tag: this.target },
@@ -247,7 +247,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
247
247
 
248
248
  const focusableId = R.join("-", [component?.id, id, index]);
249
249
 
250
- const handleFocus = (arg1: any, index?: number) => {
250
+ const handleFocus = (arg1: any, index: number) => {
251
251
  const focusFn = onFocus || noop;
252
252
  focusFn(arg1, index);
253
253
 
@@ -280,7 +280,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
280
280
  <View onLayout={this.onLayout} style={styles.container}>
281
281
  <Focusable
282
282
  id={focusableId}
283
- groupId={String(groupId || component?.id)}
283
+ groupId={groupId || component?.id}
284
284
  onFocus={handleFocus}
285
285
  onBlur={onBlur || this.onBlur}
286
286
  isParallaxDisabled={this.layout?.width > 1740}
@@ -292,18 +292,20 @@ export class TvOSCellComponent extends React.Component<Props, State> {
292
292
  style={baseCellStyles}
293
293
  isFocusable={isFocusable}
294
294
  >
295
- {(focused) => (
296
- <FocusableCell
297
- {...{
298
- index,
299
- CellRenderer,
300
- item,
301
- focused: !!(this.props.focused || selectedCell || focused),
302
- scrollTo: this.scrollTo,
303
- behavior,
304
- }}
305
- />
306
- )}
295
+ {(focused) => {
296
+ return (
297
+ <FocusableCell
298
+ {...{
299
+ index,
300
+ CellRenderer,
301
+ item,
302
+ focused: this.props.focused || selectedCell || focused,
303
+ scrollTo: this.scrollTo,
304
+ behavior,
305
+ }}
306
+ />
307
+ );
308
+ }}
307
309
  </Focusable>
308
310
  </View>
309
311
  );
@@ -1,7 +1,7 @@
1
1
  import { View } from "react-native";
2
2
  import React from "react";
3
3
  import { act, render } from "@testing-library/react-native";
4
- import { CellWithFocusable } from "../CellWithFocusable";
4
+ import { CellWithFocusable } from "../CellWithFocusable.tsx";
5
5
 
6
6
  import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
7
7
 
@@ -23,7 +23,9 @@ describe("CellWithFocusable", () => {
23
23
 
24
24
  const wrapper = renderWith(props);
25
25
 
26
- expect(wrapper.UNSAFE_getByType("View").props.state).toBe("default");
26
+ const element = wrapper.getByTestId("cell-with-focusable-cell-renderer");
27
+
28
+ expect(element.props.state).toBe("default");
27
29
  });
28
30
 
29
31
  it("should render in default state", () => {
@@ -40,8 +42,9 @@ describe("CellWithFocusable", () => {
40
42
  focusManager.isGroupItemFocused = jest.fn(() => true);
41
43
 
42
44
  const wrapper = renderWith(props);
45
+ const element = wrapper.getByTestId("cell-with-focusable-cell-renderer");
43
46
 
44
- expect(wrapper.UNSAFE_getByType("View").props.state).toBe("default");
47
+ expect(element.props.state).toBe("default");
45
48
  });
46
49
 
47
50
  it("should render in focused state", () => {
@@ -55,13 +58,17 @@ describe("CellWithFocusable", () => {
55
58
  scrollTo: jest.fn(),
56
59
  };
57
60
 
58
- focusManager.isGroupItemFocused = jest.fn(() => true);
59
61
  const wrapper = renderWith(props);
60
62
 
63
+ const focusableGroupComponent = wrapper.getByTestId(
64
+ "cell-with-focusable-cell-renderer-focusable-group"
65
+ );
66
+
61
67
  act(() => {
62
- focusManager.on.mock.calls[focusManager.on.mock.calls.length - 1][1]();
68
+ focusableGroupComponent.props.onFocus();
63
69
  });
64
70
 
65
- expect(wrapper.UNSAFE_getByType("View").props.state).toBe("focused");
71
+ const element = wrapper.getByTestId("cell-with-focusable-cell-renderer");
72
+ expect(element.props.state).toBe("focused");
66
73
  });
67
74
  });
@@ -11,7 +11,6 @@ import { ScreenScrollingContext } from "../../Contexts/ScreenScrollingContext";
11
11
 
12
12
  import { ScreenLayoutContextConsumer } from "../../Contexts/ScreenLayoutContext";
13
13
  import { createContext } from "@applicaster/zapp-react-native-utils/reactUtils/createContext";
14
- import { withComponentsMapOffsetContextConsumer } from "../../Contexts/ComponentsMapOffsetContext";
15
14
 
16
15
  // TODO | Gallery QB | Extract this
17
16
  export const ScrollInterceptorContext = createContext(
@@ -31,6 +30,5 @@ export const Cell = R.compose(
31
30
  RiverOffsetContext.withConsumer,
32
31
  HorizontalScrollContext.withConsumer,
33
32
  withConsumer,
34
- ScreenLayoutContextConsumer,
35
- withComponentsMapOffsetContextConsumer
33
+ ScreenLayoutContextConsumer
36
34
  )(Component);
@@ -9,7 +9,7 @@ import {
9
9
  focusManager,
10
10
  forceFocusableFocus,
11
11
  } from "@applicaster/zapp-react-native-utils/appUtils/focusManager/index.ios";
12
- import { findNodeHandle, ViewStyle } from "react-native";
12
+ import { findNodeHandle } from "react-native";
13
13
 
14
14
  function noop() {}
15
15
 
@@ -35,10 +35,6 @@ type Props = {
35
35
  forceFocus?: boolean;
36
36
  initialFocus?: boolean;
37
37
  onLayout?: (e: any) => void;
38
- willReceiveFocus: () => void;
39
- hasReceivedFocus: () => void;
40
- offsetUpdater: (arg1: string, arg2: number) => number;
41
- style: ViewStyle;
42
38
  };
43
39
 
44
40
  export class Focusable extends BaseFocusable<Props> {
@@ -1,25 +1,24 @@
1
1
  import * as React from "react";
2
2
 
3
- type Props =
4
- | {
5
- id: string;
6
- children: React.ReactNode;
7
- onPress?: (ref: FocusManager.TouchableRef) => void;
8
- onPressIn?: (ref: FocusManager.TouchableRef) => void;
9
- onPressOut?: (ref: FocusManager.TouchableRef) => void;
10
- onLongPress?: (ref: FocusManager.TouchableRef) => void;
11
- onFocus?: (
12
- ref: FocusManager.TouchableRef,
13
- options: FocusManager.Android.CallbackOptions
14
- ) => void;
15
- onBlur?: (
16
- ref: FocusManager.TouchableRef,
17
- options: FocusManager.Android.CallbackOptions
18
- ) => void;
19
-
20
- disableFocus?: boolean;
21
- blockFocus?: boolean;
22
- } & Partial<ParentFocus>;
3
+ type Props = {
4
+ id: string;
5
+ children: React.ReactNode;
6
+ onPress?: (ref: FocusManager.TouchableRef) => void;
7
+ onPressIn?: (ref: FocusManager.TouchableRef) => void;
8
+ onPressOut?: (ref: FocusManager.TouchableRef) => void;
9
+ onLongPress?: (ref: FocusManager.TouchableRef) => void;
10
+ onFocus?: (
11
+ ref: FocusManager.TouchableRef,
12
+ options: FocusManager.Android.CallbackOptions
13
+ ) => void;
14
+ onBlur?: (
15
+ ref: FocusManager.TouchableRef,
16
+ options: FocusManager.Android.CallbackOptions
17
+ ) => void;
18
+
19
+ disableFocus?: boolean;
20
+ blockFocus?: boolean;
21
+ } & Partial<ParentFocus>;
23
22
 
24
23
  export class Touchable extends React.Component<Props> {
25
24
  onPress(focusableRef: FocusManager.TouchableRef): void {
@@ -15,7 +15,6 @@ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
15
15
 
16
16
  import { useParentFocus, useCheckItemIdsForUnique } from "./hooks";
17
17
  import { FocusableListItemWrapper } from "./FocusableListItemWrapper";
18
- import { FocusableScrollView } from "../FocusableScrollView";
19
18
 
20
19
  const mapIndexed = R.addIndex(R.map);
21
20
 
@@ -55,7 +54,6 @@ export type Props<ItemT> = FlatListProps<ItemT> & {
55
54
  disableNextFocusUp?: boolean;
56
55
  disableNextFocusLeft?: boolean;
57
56
  disableNextFocusRight?: boolean;
58
- useScrollView?: boolean;
59
57
  } & ParentFocus;
60
58
 
61
59
  function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
@@ -90,7 +88,6 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
90
88
  data = [],
91
89
  // eslint-disable-next-line unused-imports/no-unused-vars
92
90
  omitPropsPropagation = [],
93
- useScrollView = false,
94
91
  } = props;
95
92
 
96
93
  useCheckItemIdsForUnique({ componentId: props.id, items: data });
@@ -276,7 +273,6 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
276
273
  "initialFocusDirection",
277
274
  "withStateMemory",
278
275
  "useSequentialLoading",
279
- "useScrollView",
280
276
  ...omitPropsPropagation,
281
277
  ],
282
278
  R.__
@@ -299,27 +295,15 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
299
295
  return (
300
296
  // @ts-ignore
301
297
  <ChildrenFocusDeactivatorView flex={1}>
302
- {useScrollView ? (
303
- <FocusableScrollView
304
- ref={ref}
305
- {...getFlatListProps(props)}
306
- onEndReached={onEndReached}
307
- initialNumToRender={initialNumToRender}
308
- renderItem={renderItem}
309
- focused={focused}
310
- data={data}
311
- />
312
- ) : (
313
- <FlatList
314
- focusable={false}
315
- scrollEnabled={false}
316
- ref={ref}
317
- {...getFlatListProps(props)}
318
- renderItem={renderItem}
319
- onEndReached={onEndReached}
320
- initialNumToRender={initialNumToRender}
321
- />
322
- )}
298
+ <FlatList
299
+ focusable={false}
300
+ scrollEnabled={false}
301
+ ref={ref}
302
+ {...getFlatListProps(props)}
303
+ renderItem={renderItem}
304
+ onEndReached={onEndReached}
305
+ initialNumToRender={initialNumToRender}
306
+ />
323
307
  </ChildrenFocusDeactivatorView>
324
308
  );
325
309
  }
@@ -11,13 +11,6 @@ import {
11
11
  useInitialFocus,
12
12
  } from "@applicaster/zapp-react-native-utils/focusManager";
13
13
 
14
- export type FocusableScrollViewRenderItem = (info: {
15
- item: ZappUIComponent;
16
- index: number;
17
- focused: boolean;
18
- parentFocus: ParentFocus;
19
- }) => React.ReactElement;
20
-
21
14
  export type Props = ScrollViewProps & {
22
15
  id?: number | string;
23
16
  horizontal?: boolean;
@@ -39,27 +32,17 @@ export type Props = ScrollViewProps & {
39
32
  initialFocusDirection?: FocusManager.Android.FocusNavigationDirections;
40
33
  onAllComponentsLoaded?: () => void;
41
34
  omitPropsPropagation?: Array<keyof FlatListProps<any>>;
42
- renderItem: FocusableScrollViewRenderItem;
35
+ renderItem: (info: {
36
+ item: ZappUIComponent;
37
+ index: number;
38
+ focused: boolean;
39
+ parentFocus: ParentFocus;
40
+ }) => React.ReactElement;
43
41
  } & ParentFocus;
44
42
 
45
43
  type State = boolean[];
46
44
  type Action = { index?: number; isFocusable: boolean; type?: string };
47
45
 
48
- const unwrapArray = (maybeArray) =>
49
- Array.isArray(maybeArray) ? maybeArray[0] : maybeArray;
50
-
51
- function getEntry<T>(data: T | T[], index: unknown): T {
52
- let entry;
53
-
54
- if (R.isNil(index)) {
55
- entry = unwrapArray(data);
56
- } else if (typeof index === "number") {
57
- entry = unwrapArray(data[index]);
58
- }
59
-
60
- return entry;
61
- }
62
-
63
46
  const focusableStateReducer = (
64
47
  state: State,
65
48
  { index = null, isFocusable, type = null }: Action
@@ -90,7 +73,7 @@ const extendScrollViewRef = (_ref, childCompsMeasurementsMap) => {
90
73
  };
91
74
 
92
75
  _ref.scrollToIndex = (params) => {
93
- const { index, viewOffset = 0 } = params;
76
+ const { index, viewOffset } = params;
94
77
 
95
78
  const itemByIndex = R.find(R.propEq("index", index))(
96
79
  R.values(childCompsMeasurementsMap)
@@ -146,11 +129,8 @@ function FocusableScrollViewComponent(props: Props, ref) {
146
129
  );
147
130
 
148
131
  const getFocusableEntryId = React.useCallback(
149
- (_entry: ZappEntry | null, index?: number) => {
150
- const entry: { id?: string } = getEntry(
151
- R.isNil(index) ? _entry : data,
152
- index
153
- );
132
+ (_entry: ZappEntry, index?: number) => {
133
+ const entry = R.isNil(index) ? _entry : data[index];
154
134
 
155
135
  return entry ? `${props.id}--${entry?.id}` : undefined;
156
136
  },
@@ -293,18 +273,11 @@ function FocusableScrollViewComponent(props: Props, ref) {
293
273
  const renderItem = React.useCallback(
294
274
  (item, index) => {
295
275
  const renderArgs = { item, index };
296
-
297
- const id = getFocusableEntryId(
298
- Array.isArray(item) ? item[0] : item,
299
- index
300
- );
301
-
302
- const nextFocus = getNextFocus(index);
276
+ const id = `${props.id}--${renderArgs?.item?.id}`;
277
+ const nextFocus = getNextFocus(renderArgs?.index);
303
278
 
304
279
  const onItemLayout = (event) => {
305
- childCompsMeasurementsMap.current[
306
- Array.isArray(item) ? index : item.id
307
- ] = {
280
+ childCompsMeasurementsMap.current[item.id] = {
308
281
  index,
309
282
  layout: event.nativeEvent.layout,
310
283
  };