@applicaster/zapp-react-native-ui-components 13.0.0-alpha.1360301199 → 13.0.0-alpha.1488035644

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 (25) hide show
  1. package/Components/BaseFocusable/index.ios.ts +1 -1
  2. package/Components/BaseFocusable/index.tsx +1 -1
  3. package/Components/Cell/CellWithFocusable.tsx +13 -10
  4. package/Components/Focusable/Touchable.tsx +19 -20
  5. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +66 -0
  6. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -1
  7. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -11
  8. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/__tests__/index.test.ts +93 -0
  9. package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +1 -1
  10. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  11. package/Components/MasterCell/__tests__/__snapshots__/masterCell.test.js.snap +0 -11
  12. package/Components/MasterCell/elementMapper.tsx +12 -1
  13. package/Components/MasterCell/index.tsx +84 -18
  14. package/Components/MasterCell/utils/index.ts +1 -1
  15. package/Components/Tabs/Tab.tsx +6 -6
  16. package/Components/TextInputTv/index.tsx +2 -2
  17. package/Components/Transitioner/AnimationManager.js +8 -8
  18. package/Components/VideoLive/LiveImageManager.ts +27 -1
  19. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +0 -5
  20. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +7 -6
  21. package/Components/VideoModal/ModalAnimation/utils.ts +2 -2
  22. package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +0 -32
  23. package/Contexts/ScreenContext/index.tsx +3 -2
  24. package/Decorators/ZappPipesDataConnector/__tests__/Hero.js +1 -1
  25. package/package.json +5 -5
@@ -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);
@@ -34,10 +34,10 @@ const useCellFocusedState = (
34
34
  }
35
35
  };
36
36
 
37
- focusManager.on(FOCUS_EVENTS.FOCUS, handler);
37
+ focusManager.on?.(FOCUS_EVENTS.FOCUS, handler);
38
38
 
39
39
  return () => {
40
- focusManager.removeHandler(FOCUS_EVENTS.FOCUS, handler);
40
+ focusManager.removeHandler?.(FOCUS_EVENTS.FOCUS, handler);
41
41
  };
42
42
  }, [groupId, skipFocusManagerRegistration]);
43
43
 
@@ -46,7 +46,7 @@ const useCellFocusedState = (
46
46
 
47
47
  type Props = {
48
48
  item: ZappEntry;
49
- CellRenderer: React.FunctionComponent<any>;
49
+ CellRenderer: React.ComponentType<ZappNewCellRendererProps>;
50
50
  id: string;
51
51
  groupId: string;
52
52
  onFocus: Function;
@@ -76,7 +76,7 @@ export function CellWithFocusable(props: Props) {
76
76
  } = props;
77
77
 
78
78
  const isFocused = useCellFocusedState(
79
- skipFocusManagerRegistration,
79
+ skipFocusManagerRegistration || false,
80
80
  groupId,
81
81
  id
82
82
  );
@@ -96,13 +96,16 @@ export function CellWithFocusable(props: Props) {
96
96
  }
97
97
  }, [focusedButtonId]);
98
98
 
99
- const handleToggleFocus = (value) => {
100
- setFocusedButtonId(value.focusedButtonId);
99
+ const handleToggleFocus = React.useCallback(
100
+ (value) => {
101
+ setFocusedButtonId(value.focusedButtonId);
101
102
 
102
- if (value.focusable) {
103
- onFocus(value.focusable, value.mouse);
104
- }
105
- };
103
+ if (value.focusable) {
104
+ onFocus(value.focusable, value.mouse);
105
+ }
106
+ },
107
+ [onFocus]
108
+ );
106
109
 
107
110
  return (
108
111
  <CellRenderer
@@ -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 {
@@ -0,0 +1,66 @@
1
+ import {
2
+ BorderContainerView,
3
+ getBorderPadding, // Export for testing (using a double underscore prefix is a common convention)
4
+ } from "../index";
5
+ import * as React from "react";
6
+ import { render } from "@testing-library/react-native";
7
+ import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
8
+ import { View } from "react-native";
9
+
10
+ jest.mock("@applicaster/zapp-react-native-utils/numberUtils", () => ({
11
+ toNumberWithDefaultZero: jest.fn((value) => Number(value) || 0),
12
+ }));
13
+
14
+ describe("BorderContainerView", () => {
15
+ describe("getBorderPadding", () => {
16
+ it("returns 0 for inside", () => {
17
+ expect(getBorderPadding("inside", 10)).toBe(0);
18
+ });
19
+
20
+ it("returns borderWidth / 2 for center", () => {
21
+ expect(getBorderPadding("center", 10)).toBe(5);
22
+ });
23
+
24
+ it("returns borderWidth for outside", () => {
25
+ expect(getBorderPadding("outside", 10)).toBe(10);
26
+ });
27
+
28
+ it("returns borderWidth for invalid position", () => {
29
+ // @ts-ignore
30
+ expect(getBorderPadding("other_value", 10)).toBe(10);
31
+ });
32
+ });
33
+
34
+ it("Border component renders null if no borderPosition", () => {
35
+ const style = { borderWidth: 5, borderRadius: 10, borderColor: "red" };
36
+
37
+ const padding = {
38
+ paddingTop: 2,
39
+ paddingRight: 3,
40
+ paddingBottom: 4,
41
+ paddingLeft: 5,
42
+ };
43
+
44
+ const borderPosition = null;
45
+
46
+ const { queryByTestId } = render(
47
+ <BorderContainerView
48
+ style={style}
49
+ testID="border-container"
50
+ borderPosition={borderPosition}
51
+ borderPaddingTop={toNumberWithDefaultZero(padding.paddingTop)}
52
+ borderPaddingRight={toNumberWithDefaultZero(padding.paddingRight)}
53
+ borderPaddingBottom={toNumberWithDefaultZero(padding.paddingBottom)}
54
+ borderPaddingLeft={toNumberWithDefaultZero(padding.paddingLeft)}
55
+ >
56
+ <View testID="child" />
57
+ </BorderContainerView>
58
+ );
59
+
60
+ const children = queryByTestId("border-container").children;
61
+
62
+ expect(children[1].props.testID).toBe("child");
63
+
64
+ expect(children[0].children.length).toBe(0);
65
+ });
66
+ });
@@ -28,7 +28,10 @@ const styles = StyleSheet.create({
28
28
  },
29
29
  });
30
30
 
31
- const getBorderPadding = (borderPosition: BorderPosition, borderWidth) => {
31
+ export const getBorderPadding = (
32
+ borderPosition: BorderPosition,
33
+ borderWidth: number
34
+ ) => {
32
35
  switch (borderPosition) {
33
36
  case "inside":
34
37
  return 0;
@@ -38,22 +38,16 @@ function Image({
38
38
 
39
39
  const shouldRenderImg = source && !error;
40
40
 
41
- // Default placeholder image fallback is empty string because it won't rerender
42
- // in case of undefined or {uri: undefined} source
43
- // https://github.com/facebook/react-native/issues/9195
44
- const defaultPlaceHolderImage = React.useMemo(
45
- () => ({ uri: placeholderImage || "" }),
46
- [source, error]
47
- );
41
+ const _source = shouldRenderImg
42
+ ? withDimensions(source)
43
+ : { uri: placeholderImage };
48
44
 
49
45
  return (
50
- // @ts-ignore
51
46
  <MemoizedImage
52
47
  style={style as ImageStyle}
53
48
  onError={React.useCallback(() => setErrorState(true), [])}
54
- source={
55
- shouldRenderImg ? withDimensions(source) : defaultPlaceHolderImage
56
- }
49
+ // as we have defaults as "" for placeholder image, we need to pass undefined to source to not throw warnings
50
+ source={_source?.uri ? _source : undefined}
57
51
  {...R.omit(["source"], otherProps)}
58
52
  />
59
53
  );
@@ -0,0 +1,93 @@
1
+ import { ImageBorderContainer } from "../index";
2
+ import { getImageContainerMarginStyles } from "@applicaster/zapp-react-native-utils/cellUtils";
3
+
4
+ const mockValue = (key) => {
5
+ const values = {
6
+ cell_padding_top: 1,
7
+ cell_padding_left: 2,
8
+ cell_padding_right: 3,
9
+ cell_padding_bottom: 4,
10
+ image_border_size: 5,
11
+ image_focused_border_color: "red",
12
+ image_selected_border_color: "blue",
13
+ image_focused_selected_border_color: "green",
14
+ image_border_color: "black",
15
+ image_corner_radius: 10,
16
+ image_border_position: "outside",
17
+ image_border_padding_top: 6,
18
+ image_border_padding_right: 7,
19
+ image_border_padding_bottom: 8,
20
+ image_border_padding_left: 9,
21
+ image_margin_top: 11,
22
+ image_margin_left: 12,
23
+ image_margin_right: 13,
24
+ image_margin_bottom: 14,
25
+ };
26
+
27
+ return values[key] || 0;
28
+ };
29
+
30
+ describe("ImageBorderContainer", () => {
31
+ it("calculates style properties correctly", () => {
32
+ const marginStyles = getImageContainerMarginStyles({ value: mockValue });
33
+
34
+ expect(marginStyles.marginTop).toBe(11);
35
+ expect(marginStyles.marginLeft).toBe(12);
36
+ expect(marginStyles.marginRight).toBe(13);
37
+ expect(marginStyles.marginBottom).toBe(14);
38
+
39
+ const props = {
40
+ value: mockValue,
41
+ state: "default",
42
+ imageStyles: {},
43
+ };
44
+
45
+ const result = ImageBorderContainer(props);
46
+
47
+ expect(result.style.marginTop).toBe(12); // 11 + 1
48
+ expect(result.style.marginLeft).toBe(14); // 12 + 2
49
+ expect(result.style.marginRight).toBe(16); // 13 + 3
50
+ expect(result.style.marginBottom).toBe(18); // 14 + 4
51
+ expect(result.style.borderWidth).toBe(5);
52
+ expect(result.style.borderColor).toBe("black");
53
+ expect(result.style.borderRadius).toBe(10);
54
+ expect(result.additionalProps.borderPosition).toBe("outside");
55
+ expect(result.additionalProps.borderPaddingTop).toBe(6);
56
+ expect(result.additionalProps.borderPaddingRight).toBe(7);
57
+ expect(result.additionalProps.borderPaddingBottom).toBe(8);
58
+ expect(result.additionalProps.borderPaddingLeft).toBe(9);
59
+ });
60
+
61
+ it("handles focused state correctly", () => {
62
+ const props = {
63
+ value: mockValue,
64
+ state: "focused",
65
+ imageStyles: {},
66
+ };
67
+
68
+ const result = ImageBorderContainer(props);
69
+ expect(result.style.borderColor).toBe("red");
70
+ });
71
+
72
+ it("handles selected state correctly", () => {
73
+ const props = {
74
+ value: mockValue,
75
+ state: "selected",
76
+ imageStyles: {},
77
+ };
78
+
79
+ const result = ImageBorderContainer(props);
80
+ expect(result.style.borderColor).toBe("blue");
81
+ });
82
+
83
+ it("handles focused and selected state correctly", () => {
84
+ const props = {
85
+ value: mockValue,
86
+ state: "focused_selected",
87
+ imageStyles: {},
88
+ };
89
+
90
+ const result = ImageBorderContainer(props);
91
+ expect(result.style.borderColor).toBe("green");
92
+ });
93
+ });
@@ -17,7 +17,7 @@ const SECONDARY_IMAGE_PREFIX = "secondary_image";
17
17
 
18
18
  type ImageSizing = typeof IMAGE_SIZING_FIT | typeof IMAGE_SIZING_FILL;
19
19
 
20
- type ImagePosition = typeof IMAGE_POSITION[keyof typeof IMAGE_POSITION];
20
+ type ImagePosition = (typeof IMAGE_POSITION)[keyof typeof IMAGE_POSITION];
21
21
 
22
22
  export type DisplayMode =
23
23
  | typeof DISPLAY_MODE_FIXED
@@ -39,6 +39,6 @@ describe("image with no source", () => {
39
39
  );
40
40
 
41
41
  const testInstance = testRenderer.root;
42
- expect(testInstance.findByType(Image).props.source).toEqual({ uri: "" });
42
+ expect(testInstance.findByType(Image).props.source).toBeUndefined();
43
43
  });
44
44
  });
@@ -11,7 +11,6 @@ exports[`masterCellBuilder when using a custom data adapter renders correctly 1`
11
11
  <View
12
12
  cellUUID="mocked-uuid"
13
13
  key="0"
14
- skipButtons={false}
15
14
  style={
16
15
  {
17
16
  "backgroundColor": "#2F2F2F",
@@ -41,7 +40,6 @@ exports[`masterCellBuilder when using custom containerStyle renders correctly 1`
41
40
  <View
42
41
  cellUUID="mocked-uuid"
43
42
  key="0"
44
- skipButtons={false}
45
43
  style={{}}
46
44
  wrapperRef={
47
45
  {
@@ -63,7 +61,6 @@ exports[`masterCellBuilder when using custom default components renders correctl
63
61
  <mockConstructor
64
62
  cellUUID="mocked-uuid"
65
63
  key="0"
66
- skipButtons={false}
67
64
  style={{}}
68
65
  wrapperRef={
69
66
  {
@@ -85,7 +82,6 @@ exports[`masterCellBuilder when using default options can be invoked as a React
85
82
  <View
86
83
  cellUUID="mocked-uuid"
87
84
  key="0"
88
- skipButtons={false}
89
85
  style={
90
86
  {
91
87
  "backgroundColor": "#2F2F2F",
@@ -111,7 +107,6 @@ exports[`masterCellBuilder when using default options can be invoked as a React
111
107
  cellUUID="mocked-uuid"
112
108
  key="0"
113
109
  numberOfLines={1}
114
- skipButtons={false}
115
110
  style={
116
111
  {
117
112
  "borderTopLeftRadius": 4,
@@ -125,7 +120,6 @@ exports[`masterCellBuilder when using default options can be invoked as a React
125
120
  <View
126
121
  cellUUID="mocked-uuid"
127
122
  key="1"
128
- skipButtons={false}
129
123
  style={
130
124
  {
131
125
  "height": 30,
@@ -144,7 +138,6 @@ exports[`masterCellBuilder when using default options can be invoked as a React
144
138
  key="0"
145
139
  label="Test Entry"
146
140
  numberOfLines={1}
147
- skipButtons={false}
148
141
  style={
149
142
  {
150
143
  "color": "#EFEFEF",
@@ -158,7 +151,6 @@ exports[`masterCellBuilder when using default options can be invoked as a React
158
151
  <View
159
152
  cellUUID="mocked-uuid"
160
153
  key="2"
161
- skipButtons={false}
162
154
  style={
163
155
  {
164
156
  "height": 60,
@@ -177,7 +169,6 @@ exports[`masterCellBuilder when using default options can be invoked as a React
177
169
  key="0"
178
170
  label="Summary of the test entry"
179
171
  numberOfLines={2}
180
- skipButtons={false}
181
172
  style={
182
173
  {
183
174
  "color": "#EFEFEF",
@@ -192,7 +183,6 @@ exports[`masterCellBuilder when using default options can be invoked as a React
192
183
  <View
193
184
  cellUUID="mocked-uuid"
194
185
  key="3"
195
- skipButtons={false}
196
186
  style={
197
187
  {
198
188
  "height": 42,
@@ -209,7 +199,6 @@ exports[`masterCellBuilder when using default options can be invoked as a React
209
199
  <ImageContainer
210
200
  cellUUID="mocked-uuid"
211
201
  key="0"
212
- skipButtons={false}
213
202
  style={
214
203
  {
215
204
  "height": 42,
@@ -1,4 +1,5 @@
1
1
  import * as React from "react";
2
+ import { View } from "react-native";
2
3
 
3
4
  type ElementProps = {
4
5
  type: string;
@@ -44,11 +45,21 @@ const cellPlayerTypes = new Set([
44
45
  export function elementMapper(
45
46
  components,
46
47
  otherProps?: {
48
+ preferredFocus?: boolean;
47
49
  skipButtons?: boolean;
48
50
  cellUUID?: string;
49
- [key: string]: any;
50
51
  emitAsyncElementRegistrate?: () => void;
51
52
  emitAsyncElementLayout?: () => void;
53
+ focused?: boolean;
54
+ focusedButtonId?: string;
55
+ groupId?: string;
56
+ isFocusable?: boolean;
57
+ onToggleFocus?: (arg0: unknown) => void;
58
+ prefixId?: string;
59
+ skipFocusManagerRegistration?: boolean;
60
+ component?: ZappUIComponent;
61
+ componentId?: string;
62
+ wrapperRef: React.RefObject<typeof View>;
52
63
  }
53
64
  ) {
54
65
  return function Element({
@@ -11,7 +11,24 @@ import { getEntryState, hasFocusableInsideBuilder } from "./utils";
11
11
 
12
12
  type Props = {
13
13
  item: ZappEntry;
14
- state: null | "selected" | "focused";
14
+ state: null | "selected" | "focused" | "default";
15
+ emitAsyncElementRegistrate?: () => void;
16
+ emitAsyncElementLayout?: () => void;
17
+ skipButtons?: boolean;
18
+ cellUUID?: string;
19
+ // New props from CellWithFocusable
20
+ groupId?: string;
21
+ onToggleFocus?: (arg0: unknown) => void;
22
+ prefixId?: string;
23
+ focusedButtonId?: string;
24
+ preferredFocus?: boolean;
25
+ skipFocusManagerRegistration?: boolean;
26
+ isFocusable?: boolean;
27
+ focused?: boolean;
28
+ // New props from Gallery
29
+ component?: ZappUIComponent;
30
+ componentId?: string;
31
+ screenId: string;
15
32
  };
16
33
 
17
34
  const defaultContainerStyle = { flex: 1 };
@@ -39,6 +56,24 @@ type MasterCellBuilderOptions = {
39
56
  };
40
57
  };
41
58
 
59
+ // retrieve screendata from route
60
+ const useMasterCellScreen = (screenId?: string) => {
61
+ let _screenId = screenId;
62
+ const { screenData } = useRoute();
63
+
64
+ if (!screenId) {
65
+ // get screenId from targetScreen or screenData
66
+ _screenId =
67
+ screenData && "targetScreen" in screenData
68
+ ? screenData?.targetScreen?.id
69
+ : screenData?.id;
70
+ }
71
+
72
+ const { screen } = useScreenState(_screenId);
73
+
74
+ return screen;
75
+ };
76
+
42
77
  export function masterCellBuilder({
43
78
  components = defaultComponents,
44
79
  cellConfiguration,
@@ -63,15 +98,8 @@ export function masterCellBuilder({
63
98
  * inflated with the data coming from the data source
64
99
  * @param {"selected" | "focused" | null} props.state state of the component
65
100
  */
66
- function MasterCell({ item, state, ...otherProps }: Props) {
67
- const { screenData } = useRoute();
68
-
69
- const screenId =
70
- screenData && "targetScreen" in screenData
71
- ? screenData?.targetScreen?.id
72
- : screenData?.id;
73
-
74
- const { screen } = useScreenState(screenId);
101
+ function MasterCell({ item, state, screenId, ...otherProps }: Props) {
102
+ const screen = useMasterCellScreen(screenId);
75
103
 
76
104
  const selectedState = screen?.selectedEntry;
77
105
 
@@ -97,18 +125,56 @@ export function masterCellBuilder({
97
125
  item?.id,
98
126
  ]);
99
127
 
100
- const remapElements = mapElementWithKey(
101
- elementMapper(componentsMap, {
102
- ...otherProps,
103
- wrapperRef,
104
- cellUUID,
105
- skipButtons,
106
- })
128
+ const remapElements = React.useMemo(
129
+ () =>
130
+ mapElementWithKey(
131
+ elementMapper(componentsMap, {
132
+ wrapperRef,
133
+ emitAsyncElementRegistrate: otherProps.emitAsyncElementRegistrate,
134
+ emitAsyncElementLayout: otherProps.emitAsyncElementLayout,
135
+ preferredFocus: otherProps.preferredFocus,
136
+ cellUUID: cellUUID || otherProps.cellUUID,
137
+ skipButtons: skipButtons || otherProps.skipButtons,
138
+ // cellWithFocusable
139
+ focused: otherProps.focused,
140
+ focusedButtonId: otherProps.focusedButtonId,
141
+ groupId: otherProps.groupId,
142
+ isFocusable: otherProps.isFocusable,
143
+ onToggleFocus: otherProps.onToggleFocus,
144
+ prefixId: otherProps.prefixId,
145
+ skipFocusManagerRegistration:
146
+ otherProps.skipFocusManagerRegistration,
147
+ // gallery
148
+ component: otherProps.component,
149
+ componentId: otherProps.componentId,
150
+ })
151
+ ),
152
+ [
153
+ componentsMap,
154
+ otherProps.emitAsyncElementRegistrate,
155
+ otherProps.emitAsyncElementLayout,
156
+ cellUUID || otherProps.cellUUID,
157
+ skipButtons || otherProps.skipButtons,
158
+ otherProps.focused,
159
+ otherProps.focusedButtonId,
160
+ otherProps.groupId,
161
+ otherProps.isFocusable,
162
+ otherProps.onToggleFocus,
163
+ otherProps.prefixId,
164
+ otherProps.skipFocusManagerRegistration,
165
+ otherProps.component,
166
+ otherProps.componentId,
167
+ ]
168
+ );
169
+
170
+ const renderElements = React.useMemo(
171
+ () => elements.map(remapElements),
172
+ [remapElements, elements]
107
173
  );
108
174
 
109
175
  return (
110
176
  <View style={containerStyle} ref={wrapperRef}>
111
- {elements.map(remapElements)}
177
+ {renderElements}
112
178
  </View>
113
179
  );
114
180
  }
@@ -103,7 +103,7 @@ export const useFilterChildren = <
103
103
  item: any;
104
104
  pluginIdentifier: string;
105
105
  };
106
- }
106
+ },
107
107
  >(
108
108
  children: T[]
109
109
  ): T[] => {
@@ -69,8 +69,8 @@ const getStyles = (configuration, selected, focused) => {
69
69
  ? tab_cell_background_color_selected_active
70
70
  : tab_cell_background_color_selected_default
71
71
  : focused
72
- ? tab_cell_background_color_active
73
- : tab_cell_background_color_default,
72
+ ? tab_cell_background_color_active
73
+ : tab_cell_background_color_default,
74
74
  justifyContent: "center",
75
75
  alignItems: "center",
76
76
  position: "relative",
@@ -85,8 +85,8 @@ const getStyles = (configuration, selected, focused) => {
85
85
  ? tab_cell_border_color_active_focused
86
86
  : tab_cell_border_color_active
87
87
  : focused
88
- ? tab_cell_border_color_default_focused
89
- : tab_cell_border_color_default,
88
+ ? tab_cell_border_color_default_focused
89
+ : tab_cell_border_color_default,
90
90
  },
91
91
  label: {
92
92
  fontFamily: text_label_font_family,
@@ -98,8 +98,8 @@ const getStyles = (configuration, selected, focused) => {
98
98
  ? text_label_selected_active_font_color
99
99
  : text_label_selected_default_font_color
100
100
  : focused
101
- ? text_label_active_font_color
102
- : text_label_default_font_color,
101
+ ? text_label_active_font_color
102
+ : text_label_default_font_color,
103
103
  },
104
104
  underline: {
105
105
  position: "absolute",
@@ -94,8 +94,8 @@ function TextInputTV(props: Props, ref) {
94
94
  styles.textAlign === "center"
95
95
  ? styles.textAlign
96
96
  : styles.textAlign === "left"
97
- ? "right"
98
- : "left";
97
+ ? "right"
98
+ : "left";
99
99
 
100
100
  return { style: { ...styles, textAlign } };
101
101
  }
@@ -3,19 +3,19 @@ import { Animated } from "react-native";
3
3
  import { NAV_ACTION_PUSH, NAV_ACTION_BACK } from "./Transitioner";
4
4
 
5
5
  type TransitionConfig = {
6
- duration: number,
7
- easing: any,
6
+ duration: number;
7
+ easing: any;
8
8
  from: {
9
- style: any,
10
- },
9
+ style: any;
10
+ };
11
11
  to: {
12
- style: any,
13
- },
12
+ style: any;
13
+ };
14
14
  };
15
15
 
16
16
  type Props = {
17
- transitionConfig: TransitionConfig,
18
- contentStyle: { [string]: any },
17
+ transitionConfig: TransitionConfig;
18
+ contentStyle: { [string]: any };
19
19
  };
20
20
 
21
21
  /**
@@ -8,6 +8,8 @@ import { loggerLiveImageManager } from "./loggerHelper";
8
8
  import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
9
9
  import { Component } from "react";
10
10
 
11
+ const TIMEOUT_FOR_DELAY_CHECK_PLAYER_POSITION = 500; // ms
12
+
11
13
  const { log_debug, log_info, log_error } = loggerLiveImageManager;
12
14
 
13
15
  export type LiveImageManagerEvent =
@@ -62,6 +64,9 @@ export class LiveImageManager implements PlayerLifecycleListener {
62
64
  protected currentlyPlaying: LiveImage | null = null;
63
65
  protected primaryPlayer: Player | null = null;
64
66
 
67
+ private checkPlayerPositionTimeout: ReturnType<typeof setTimeout> | null =
68
+ null;
69
+
65
70
  protected listeners: Record<
66
71
  string,
67
72
  Record<LiveImageManagerEvent, (event?: Record<string, any>) => void>
@@ -118,6 +123,11 @@ export class LiveImageManager implements PlayerLifecycleListener {
118
123
  });
119
124
  };
120
125
 
126
+ private cancelCheckPlayerPositionTimeout = () => {
127
+ clearTimeout(this.checkPlayerPositionTimeout);
128
+ this.checkPlayerPositionTimeout = null;
129
+ };
130
+
121
131
  public onViewportEnter = (item: LiveImage) => {
122
132
  log_debug(
123
133
  `onViewportEnter: live-image ${playerInfo(
@@ -125,7 +135,21 @@ export class LiveImageManager implements PlayerLifecycleListener {
125
135
  )}, primary ${playerInfo(this.primaryPlayer)}`
126
136
  );
127
137
 
128
- this.checkPlayerPosition(item);
138
+ if (!isTV()) {
139
+ // mobile only
140
+ // we have to delay running checkPlayerPosition, because sometimes on fast scrolling we get wrong order onEnter, then onLeave.
141
+ // which could cause select wrong item to play
142
+
143
+ this.cancelCheckPlayerPositionTimeout();
144
+
145
+ this.checkPlayerPositionTimeout = setTimeout(() => {
146
+ this.cancelCheckPlayerPositionTimeout();
147
+
148
+ this.checkPlayerPosition(item);
149
+ }, TIMEOUT_FOR_DELAY_CHECK_PLAYER_POSITION);
150
+ } else {
151
+ this.checkPlayerPosition(item);
152
+ }
129
153
  };
130
154
 
131
155
  public onViewportLeave = (item: LiveImage) => {
@@ -246,6 +270,8 @@ export class LiveImageManager implements PlayerLifecycleListener {
246
270
  };
247
271
 
248
272
  public checkPlayerPosition = (item: LiveImage) => {
273
+ this.cancelCheckPlayerPositionTimeout();
274
+
249
275
  log_debug(
250
276
  `checkPlayerPosition: live-image playerId: ${playerInfo(
251
277
  item.player
@@ -31,11 +31,6 @@ exports[`PlayerLiveImageComponent should render correctly with default props 1`]
31
31
  playerId="player1"
32
32
  resizeMode="cover"
33
33
  screenConfig={{}}
34
- source={
35
- {
36
- "uri": "",
37
- }
38
- }
39
34
  style={{}}
40
35
  />
41
36
  </View>
@@ -100,10 +100,11 @@ export const AnimationView = ({
100
100
  const moveUpValue = additionalData.saveArea
101
101
  ? -insets.top + (isAudioItem ? 0 : progressBarHeight)
102
102
  : isTablet
103
- ? isTabletLandscape && (!isAudioItem || (isAudioItem && inlineAudioPlayer))
104
- ? -tabletLandscapePlayerTopPosition + progressBarHeight
105
- : -130
106
- : -50 + progressBarHeight;
103
+ ? isTabletLandscape &&
104
+ (!isAudioItem || (isAudioItem && inlineAudioPlayer))
105
+ ? -tabletLandscapePlayerTopPosition + progressBarHeight
106
+ : -130
107
+ : -50 + progressBarHeight;
107
108
 
108
109
  const moveComponentHorizontalValue = additionalData.moveValue
109
110
  ? isRTL
@@ -434,8 +435,8 @@ export const AnimationComponent = (props: Props) => {
434
435
  const Component = useAnimation
435
436
  ? AnimationView
436
437
  : style
437
- ? View
438
- : React.Fragment;
438
+ ? View
439
+ : React.Fragment;
439
440
 
440
441
  if (
441
442
  additionalData.extraAnimation &&
@@ -108,8 +108,8 @@ export const calculateAnimationValue = (animationType, dragPosition, data) => {
108
108
  : { forWidth: 3, forHeight: 3 }
109
109
  : { forWidth: 2, forHeight: 2 }
110
110
  : isTabletLandscape
111
- ? { forWidth: 8, forHeight: 6.5 }
112
- : { forWidth: 3.5, forHeight: 2 };
111
+ ? { forWidth: 8, forHeight: 6.5 }
112
+ : { forWidth: 3.5, forHeight: 2 };
113
113
 
114
114
  const minWidth =
115
115
  isAudioItem && !inlineAudioPlayer ? minimisedHeight : minimisedWidth;
@@ -12,8 +12,6 @@ exports[`DefaultCellRenderer returns a react component and it renders correctly
12
12
  <View
13
13
  cellUUID="mocked-uuid"
14
14
  key="0"
15
- skipButtons={false}
16
- store={null}
17
15
  style={
18
16
  {
19
17
  "backgroundColor": "transparent",
@@ -31,7 +29,6 @@ exports[`DefaultCellRenderer returns a react component and it renders correctly
31
29
  <ImageContainer
32
30
  cellUUID="mocked-uuid"
33
31
  key="0"
34
- skipButtons={false}
35
32
  style={
36
33
  {
37
34
  "borderRadius": 3,
@@ -43,8 +40,6 @@ exports[`DefaultCellRenderer returns a react component and it renders correctly
43
40
  <View
44
41
  cellUUID="mocked-uuid"
45
42
  key="1"
46
- skipButtons={false}
47
- store={null}
48
43
  wrapperRef={
49
44
  {
50
45
  "current": null,
@@ -56,7 +51,6 @@ exports[`DefaultCellRenderer returns a react component and it renders correctly
56
51
  key="0"
57
52
  label=""
58
53
  numberOfLines={2}
59
- skipButtons={false}
60
54
  style={
61
55
  {
62
56
  "color": "#000",
@@ -83,8 +77,6 @@ exports[`DefaultCellRenderer returns a react component for LG TVs 1`] = `
83
77
  <View
84
78
  cellUUID="mocked-uuid"
85
79
  key="0"
86
- skipButtons={false}
87
- store={null}
88
80
  style={
89
81
  {
90
82
  "aspectRatio": 0.880733945,
@@ -101,8 +93,6 @@ exports[`DefaultCellRenderer returns a react component for LG TVs 1`] = `
101
93
  <View
102
94
  cellUUID="mocked-uuid"
103
95
  key="0"
104
- skipButtons={false}
105
- store={null}
106
96
  style={
107
97
  {
108
98
  "backgroundColor": "rgba(47,47,47,1.0)",
@@ -120,8 +110,6 @@ exports[`DefaultCellRenderer returns a react component for LG TVs 1`] = `
120
110
  <View
121
111
  cellUUID="mocked-uuid"
122
112
  key="0"
123
- skipButtons={false}
124
- store={null}
125
113
  wrapperRef={
126
114
  {
127
115
  "current": null,
@@ -131,7 +119,6 @@ exports[`DefaultCellRenderer returns a react component for LG TVs 1`] = `
131
119
  <ImageContainer
132
120
  cellUUID="mocked-uuid"
133
121
  key="0"
134
- skipButtons={false}
135
122
  style={
136
123
  {
137
124
  "aspectRatio": 1.7782608696,
@@ -142,8 +129,6 @@ exports[`DefaultCellRenderer returns a react component for LG TVs 1`] = `
142
129
  <View
143
130
  cellUUID="mocked-uuid"
144
131
  key="1"
145
- skipButtons={false}
146
- store={null}
147
132
  wrapperRef={
148
133
  {
149
134
  "current": null,
@@ -154,7 +139,6 @@ exports[`DefaultCellRenderer returns a react component for LG TVs 1`] = `
154
139
  key="0"
155
140
  label=""
156
141
  numberOfLines={2}
157
- skipButtons={false}
158
142
  style={
159
143
  {
160
144
  "color": "rgba(239,239,239,1.0)",
@@ -170,8 +154,6 @@ exports[`DefaultCellRenderer returns a react component for LG TVs 1`] = `
170
154
  <View
171
155
  cellUUID="mocked-uuid"
172
156
  key="2"
173
- skipButtons={false}
174
- store={null}
175
157
  style={
176
158
  {
177
159
  "paddingHorizontal": "6%",
@@ -188,7 +170,6 @@ exports[`DefaultCellRenderer returns a react component for LG TVs 1`] = `
188
170
  key="0"
189
171
  label=""
190
172
  numberOfLines={1}
191
- skipButtons={false}
192
173
  style={
193
174
  {
194
175
  "color": "rgba(239,239,239,1.0)",
@@ -216,8 +197,6 @@ exports[`DefaultCellRenderer returns a react component for Samsung TVs 1`] = `
216
197
  <View
217
198
  cellUUID="mocked-uuid"
218
199
  key="0"
219
- skipButtons={false}
220
- store={null}
221
200
  style={
222
201
  {
223
202
  "aspectRatio": 0.880733945,
@@ -234,8 +213,6 @@ exports[`DefaultCellRenderer returns a react component for Samsung TVs 1`] = `
234
213
  <View
235
214
  cellUUID="mocked-uuid"
236
215
  key="0"
237
- skipButtons={false}
238
- store={null}
239
216
  style={
240
217
  {
241
218
  "backgroundColor": "rgba(47,47,47,1.0)",
@@ -253,8 +230,6 @@ exports[`DefaultCellRenderer returns a react component for Samsung TVs 1`] = `
253
230
  <View
254
231
  cellUUID="mocked-uuid"
255
232
  key="0"
256
- skipButtons={false}
257
- store={null}
258
233
  wrapperRef={
259
234
  {
260
235
  "current": null,
@@ -264,7 +239,6 @@ exports[`DefaultCellRenderer returns a react component for Samsung TVs 1`] = `
264
239
  <ImageContainer
265
240
  cellUUID="mocked-uuid"
266
241
  key="0"
267
- skipButtons={false}
268
242
  style={
269
243
  {
270
244
  "aspectRatio": 1.7782608696,
@@ -275,8 +249,6 @@ exports[`DefaultCellRenderer returns a react component for Samsung TVs 1`] = `
275
249
  <View
276
250
  cellUUID="mocked-uuid"
277
251
  key="1"
278
- skipButtons={false}
279
- store={null}
280
252
  wrapperRef={
281
253
  {
282
254
  "current": null,
@@ -287,7 +259,6 @@ exports[`DefaultCellRenderer returns a react component for Samsung TVs 1`] = `
287
259
  key="0"
288
260
  label=""
289
261
  numberOfLines={2}
290
- skipButtons={false}
291
262
  style={
292
263
  {
293
264
  "color": "rgba(239,239,239,1.0)",
@@ -303,8 +274,6 @@ exports[`DefaultCellRenderer returns a react component for Samsung TVs 1`] = `
303
274
  <View
304
275
  cellUUID="mocked-uuid"
305
276
  key="2"
306
- skipButtons={false}
307
- store={null}
308
277
  style={
309
278
  {
310
279
  "paddingHorizontal": "6%",
@@ -321,7 +290,6 @@ exports[`DefaultCellRenderer returns a react component for Samsung TVs 1`] = `
321
290
  key="0"
322
291
  label=""
323
292
  numberOfLines={1}
324
- skipButtons={false}
325
293
  style={
326
294
  {
327
295
  "color": "rgba(239,239,239,1.0)",
@@ -99,8 +99,9 @@ export function ScreenContextProvider({
99
99
  const isNested = useNestedNavigationContext();
100
100
  const currentScreenScreenData = useCurrentScreenData();
101
101
 
102
- const screenNavBarStateRef =
103
- useRef<null | ReturnType<typeof createStore>>(null);
102
+ const screenNavBarStateRef = useRef<null | ReturnType<typeof createStore>>(
103
+ null
104
+ );
104
105
 
105
106
  const getScreenNavBarState = useCallback(() => {
106
107
  if (screenNavBarStateRef.current !== null) {
@@ -2,7 +2,7 @@ import React, { useEffect } from "react";
2
2
  import { View } from "react-native";
3
3
 
4
4
  type Props = {
5
- onLoadFinished: () => void,
5
+ onLoadFinished: () => void;
6
6
  };
7
7
 
8
8
  export function Hero(props: Props) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-ui-components",
3
- "version": "13.0.0-alpha.1360301199",
3
+ "version": "13.0.0-alpha.1488035644",
4
4
  "description": "Applicaster Zapp React Native ui components for the Quick Brick App",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -34,10 +34,10 @@
34
34
  "redux-mock-store": "^1.5.3"
35
35
  },
36
36
  "dependencies": {
37
- "@applicaster/applicaster-types": "13.0.0-alpha.1360301199",
38
- "@applicaster/zapp-react-native-bridge": "13.0.0-alpha.1360301199",
39
- "@applicaster/zapp-react-native-redux": "13.0.0-alpha.1360301199",
40
- "@applicaster/zapp-react-native-utils": "13.0.0-alpha.1360301199",
37
+ "@applicaster/applicaster-types": "13.0.0-alpha.1488035644",
38
+ "@applicaster/zapp-react-native-bridge": "13.0.0-alpha.1488035644",
39
+ "@applicaster/zapp-react-native-redux": "13.0.0-alpha.1488035644",
40
+ "@applicaster/zapp-react-native-utils": "13.0.0-alpha.1488035644",
41
41
  "promise": "^8.3.0",
42
42
  "react-router-native": "^5.1.2",
43
43
  "url": "^0.11.0",