@applicaster/zapp-react-native-ui-components 12.0.0-rc.81 → 12.0.0-rc.83
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.
- package/Components/Focusable/Focusable.tsx +6 -1
- package/Components/FocusableGroup/index.tsx +10 -2
- package/Components/Screen/TV/index.web.tsx +0 -1
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +4 -10
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +8 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +6 -4
- package/Components/VideoModal/PlayerWrapper.tsx +1 -1
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +32 -12
- package/Contexts/FocusableGroupContext/FocusableGroupContext.ts +3 -0
- package/Contexts/FocusableGroupContext/FocusableGroupContextProvider.tsx +16 -0
- package/Contexts/FocusableGroupContext/__tests__/FocusableGroupContextProvider.test.tsx +22 -0
- package/Contexts/FocusableGroupContext/__tests__/withFocusableContext.test.tsx +26 -0
- package/Contexts/FocusableGroupContext/index.ts +7 -0
- package/Contexts/FocusableGroupContext/withFocusableContext.tsx +17 -0
- package/package.json +5 -5
- /package/Components/FocusableGroup/{index.android.js → index.android.ts} +0 -0
- /package/Components/FocusableGroup/{index.ios.js → index.ios.ts} +0 -0
|
@@ -4,6 +4,7 @@ import * as R from "ramda";
|
|
|
4
4
|
import { BaseFocusable } from "../BaseFocusable";
|
|
5
5
|
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
|
|
6
6
|
import { LONG_KEY_PRESS_TIMEOUT } from "@applicaster/quick-brick-core/const";
|
|
7
|
+
import { withFocusableContext } from "../../Contexts/FocusableGroupContext/withFocusableContext";
|
|
7
8
|
|
|
8
9
|
type Props = {
|
|
9
10
|
initialFocus?: boolean;
|
|
@@ -23,7 +24,7 @@ type Props = {
|
|
|
23
24
|
style?: React.CSSProperties;
|
|
24
25
|
};
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
class Focusable extends BaseFocusable<Props> {
|
|
27
28
|
isGroup: boolean;
|
|
28
29
|
mouse: boolean;
|
|
29
30
|
longPressTimeout = null;
|
|
@@ -198,3 +199,7 @@ export class Focusable extends BaseFocusable<Props> {
|
|
|
198
199
|
);
|
|
199
200
|
}
|
|
200
201
|
}
|
|
202
|
+
|
|
203
|
+
const FocusableWithFocusableContext = withFocusableContext(Focusable);
|
|
204
|
+
|
|
205
|
+
export { FocusableWithFocusableContext as Focusable };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
|
|
3
3
|
import { BaseFocusable } from "../BaseFocusable";
|
|
4
|
+
import { FocusableGroupContextProvider } from "../../Contexts/FocusableGroupContext";
|
|
5
|
+
import { withFocusableContext } from "../../Contexts/FocusableGroupContext/withFocusableContext";
|
|
4
6
|
|
|
5
7
|
type Props = {
|
|
6
8
|
testID?: string;
|
|
@@ -29,7 +31,7 @@ type Props = {
|
|
|
29
31
|
excludeFromFocusSearching?: boolean;
|
|
30
32
|
};
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
class FocusableGroup extends BaseFocusable<Props> {
|
|
33
35
|
constructor(props) {
|
|
34
36
|
super(props);
|
|
35
37
|
this.isGroup = true;
|
|
@@ -82,8 +84,14 @@ export class FocusableGroup extends BaseFocusable<Props> {
|
|
|
82
84
|
style={style}
|
|
83
85
|
ref={this.ref}
|
|
84
86
|
>
|
|
85
|
-
{
|
|
87
|
+
<FocusableGroupContextProvider id={id}>
|
|
88
|
+
{children}
|
|
89
|
+
</FocusableGroupContextProvider>
|
|
86
90
|
</div>
|
|
87
91
|
);
|
|
88
92
|
}
|
|
89
93
|
}
|
|
94
|
+
|
|
95
|
+
const FocusableGroupWithFocusableContext = withFocusableContext(FocusableGroup);
|
|
96
|
+
|
|
97
|
+
export { FocusableGroupWithFocusableContext as FocusableGroup };
|
|
@@ -162,7 +162,6 @@ export const Screen = ({ route, Components }: Props) => {
|
|
|
162
162
|
<View style={[styles.container, { backgroundColor }]}>
|
|
163
163
|
<NavBarContainer isVisible={isNavBarVisible} onReady={noop}>
|
|
164
164
|
<NavBar
|
|
165
|
-
groupId={route}
|
|
166
165
|
isVisible={isNavBarVisible}
|
|
167
166
|
menuPlugin={menuPlugin}
|
|
168
167
|
navigationProps={navigationProps}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useRef, useState } from "react";
|
|
2
|
-
import { Animated, View
|
|
2
|
+
import { Animated, View } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
5
5
|
|
|
@@ -33,10 +33,6 @@ type Props = {
|
|
|
33
33
|
additionalData?: { [key: string]: any };
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
const styles = StyleSheet.create({
|
|
37
|
-
flex: { flex: 1 },
|
|
38
|
-
});
|
|
39
|
-
|
|
40
36
|
export const AnimationView = ({
|
|
41
37
|
animationType,
|
|
42
38
|
style,
|
|
@@ -54,18 +50,17 @@ export const AnimationView = ({
|
|
|
54
50
|
tabletLandscapePlayerTopPosition,
|
|
55
51
|
setTabletLandscapePlayerTopPosition,
|
|
56
52
|
modalSnapPoints,
|
|
53
|
+
startComponentsAnimationDistance,
|
|
57
54
|
} = useModalAnimationContext();
|
|
58
55
|
|
|
59
56
|
const isRTL = useIsRTL();
|
|
60
57
|
const isAppActive = useAppState(true);
|
|
61
58
|
|
|
62
59
|
const {
|
|
63
|
-
height: screenHeight,
|
|
64
60
|
width: screenWidth,
|
|
65
61
|
deviceInfo: { isTablet, isTabletLandscape },
|
|
66
62
|
} = useDimensions("window", { deviceInfo: true });
|
|
67
63
|
|
|
68
|
-
const startAnimationDistance = Math.round((screenHeight * 60) / 100);
|
|
69
64
|
const { videoModalState } = useNavigation();
|
|
70
65
|
const bottomTabBarHeight = useGetBottomTabBarHeight();
|
|
71
66
|
const minimisedWidth = defaultAspectRatioWidth(minimisedHeight);
|
|
@@ -346,7 +341,7 @@ export const AnimationView = ({
|
|
|
346
341
|
animatedValue,
|
|
347
342
|
calculationData,
|
|
348
343
|
modalSnapPoint: modalSnapPoints[1],
|
|
349
|
-
|
|
344
|
+
startComponentsAnimationDistance,
|
|
350
345
|
startComponentsAnimation,
|
|
351
346
|
setStartComponentsAnimation,
|
|
352
347
|
getAnimationValue,
|
|
@@ -371,7 +366,7 @@ export const AnimationView = ({
|
|
|
371
366
|
animatedValue,
|
|
372
367
|
calculationData,
|
|
373
368
|
modalSnapPoint: modalSnapPoints[1],
|
|
374
|
-
|
|
369
|
+
startComponentsAnimationDistance,
|
|
375
370
|
startComponentsAnimation,
|
|
376
371
|
setStartComponentsAnimation,
|
|
377
372
|
getAnimationValue,
|
|
@@ -393,7 +388,6 @@ export const AnimationView = ({
|
|
|
393
388
|
ref={animationComponentRef}
|
|
394
389
|
style={[
|
|
395
390
|
...preparedStyles,
|
|
396
|
-
additionalData.saveArea ? styles.flex : null,
|
|
397
391
|
(videoModalState.mode === "MAXIMIZED" ||
|
|
398
392
|
videoModalState.mode === "MINIMIZED" ||
|
|
399
393
|
(videoModalState.mode === "PIP" && isAppActive)) &&
|
|
@@ -39,6 +39,7 @@ export type ModalAnimationContextT = {
|
|
|
39
39
|
setLastSnap: (value: number) => void;
|
|
40
40
|
tabletLandscapePlayerTopPosition: number;
|
|
41
41
|
setTabletLandscapePlayerTopPosition: (value: number) => void;
|
|
42
|
+
startComponentsAnimationDistance: number;
|
|
42
43
|
};
|
|
43
44
|
|
|
44
45
|
const ReactContext = React.createContext<ModalAnimationContextT>({
|
|
@@ -62,6 +63,7 @@ const ReactContext = React.createContext<ModalAnimationContextT>({
|
|
|
62
63
|
setLastSnap: () => null,
|
|
63
64
|
tabletLandscapePlayerTopPosition: 0,
|
|
64
65
|
setTabletLandscapePlayerTopPosition: () => null,
|
|
66
|
+
startComponentsAnimationDistance: 0,
|
|
65
67
|
});
|
|
66
68
|
|
|
67
69
|
export function useModalAnimationContext() {
|
|
@@ -97,6 +99,11 @@ const Provider = ({ children }: { children: React.ReactNode }) => {
|
|
|
97
99
|
const { bottom: bottomSafeArea } = useSafeAreaInsets();
|
|
98
100
|
const bottomTabBarHeight = useGetBottomTabBarHeight();
|
|
99
101
|
|
|
102
|
+
const startComponentsAnimationDistance = React.useMemo(
|
|
103
|
+
() => Math.round((height * 60) / 100),
|
|
104
|
+
[height]
|
|
105
|
+
);
|
|
106
|
+
|
|
100
107
|
/*
|
|
101
108
|
If bottomTabBarHeight is equal 0 it means an app does not use bottomTabBar.
|
|
102
109
|
Because of this we need to minus bottom SafeArea offset.
|
|
@@ -134,6 +141,7 @@ const Provider = ({ children }: { children: React.ReactNode }) => {
|
|
|
134
141
|
setLastSnap,
|
|
135
142
|
tabletLandscapePlayerTopPosition,
|
|
136
143
|
setTabletLandscapePlayerTopPosition,
|
|
144
|
+
startComponentsAnimationDistance,
|
|
137
145
|
}}
|
|
138
146
|
>
|
|
139
147
|
{children}
|
|
@@ -233,7 +233,7 @@ export const gestureListenerHelper = (data) => {
|
|
|
233
233
|
animatedValue,
|
|
234
234
|
calculationData,
|
|
235
235
|
modalSnapPoint,
|
|
236
|
-
|
|
236
|
+
startComponentsAnimationDistance,
|
|
237
237
|
startComponentsAnimation,
|
|
238
238
|
setStartComponentsAnimation,
|
|
239
239
|
getAnimationValue,
|
|
@@ -243,7 +243,7 @@ export const gestureListenerHelper = (data) => {
|
|
|
243
243
|
if (listenerValue <= 0) {
|
|
244
244
|
if (
|
|
245
245
|
preparedValue >= 0 &&
|
|
246
|
-
preparedValue <= modalSnapPoint -
|
|
246
|
+
preparedValue <= modalSnapPoint - startComponentsAnimationDistance
|
|
247
247
|
) {
|
|
248
248
|
!startComponentsAnimation && setStartComponentsAnimation(true);
|
|
249
249
|
|
|
@@ -263,9 +263,11 @@ export const gestureListenerHelper = (data) => {
|
|
|
263
263
|
animatedValue.setValue(value);
|
|
264
264
|
}
|
|
265
265
|
} else {
|
|
266
|
-
if (preparedValue >=
|
|
266
|
+
if (preparedValue >= startComponentsAnimationDistance) {
|
|
267
267
|
!startComponentsAnimation && setStartComponentsAnimation(true);
|
|
268
|
-
const value = Math.round(
|
|
268
|
+
const value = Math.round(
|
|
269
|
+
preparedValue - startComponentsAnimationDistance
|
|
270
|
+
);
|
|
269
271
|
|
|
270
272
|
animatedValue.setValue(
|
|
271
273
|
calculateAnimationValue(animationType, value, calculationData)
|
|
@@ -197,7 +197,7 @@ export const PlayerWrapper = (props: Props) => {
|
|
|
197
197
|
<AnimationComponent
|
|
198
198
|
animationType={ComponentAnimationType.moveUpComponent}
|
|
199
199
|
additionalData={{ saveArea: true }}
|
|
200
|
-
style={directionStyles(isTabletLandscape)}
|
|
200
|
+
style={[directionStyles(isTabletLandscape), defaultStyles.flex]}
|
|
201
201
|
>
|
|
202
202
|
<PathnameContext.Provider value={pathname}>
|
|
203
203
|
<ScreenContextProvider pathname={pathname}>
|
|
@@ -42,9 +42,14 @@ exports[`PlayerWrapper renders inline 1`] = `
|
|
|
42
42
|
}
|
|
43
43
|
animationType="moveUpComponent"
|
|
44
44
|
style={
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
Array [
|
|
46
|
+
Object {
|
|
47
|
+
"flexDirection": "column",
|
|
48
|
+
},
|
|
49
|
+
Object {
|
|
50
|
+
"flex": 1,
|
|
51
|
+
},
|
|
52
|
+
]
|
|
48
53
|
}
|
|
49
54
|
>
|
|
50
55
|
<View
|
|
@@ -120,9 +125,14 @@ exports[`PlayerWrapper renders inline and docked 1`] = `
|
|
|
120
125
|
}
|
|
121
126
|
animationType="moveUpComponent"
|
|
122
127
|
style={
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
128
|
+
Array [
|
|
129
|
+
Object {
|
|
130
|
+
"flexDirection": "column",
|
|
131
|
+
},
|
|
132
|
+
Object {
|
|
133
|
+
"flex": 1,
|
|
134
|
+
},
|
|
135
|
+
]
|
|
126
136
|
}
|
|
127
137
|
>
|
|
128
138
|
<View
|
|
@@ -198,9 +208,14 @@ exports[`PlayerWrapper renders inline on tablet in landscape orientation 1`] = `
|
|
|
198
208
|
}
|
|
199
209
|
animationType="moveUpComponent"
|
|
200
210
|
style={
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
211
|
+
Array [
|
|
212
|
+
Object {
|
|
213
|
+
"flexDirection": "row",
|
|
214
|
+
},
|
|
215
|
+
Object {
|
|
216
|
+
"flex": 1,
|
|
217
|
+
},
|
|
218
|
+
]
|
|
204
219
|
}
|
|
205
220
|
>
|
|
206
221
|
<View
|
|
@@ -292,9 +307,14 @@ exports[`PlayerWrapper renders properly 1`] = `
|
|
|
292
307
|
}
|
|
293
308
|
animationType="moveUpComponent"
|
|
294
309
|
style={
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
310
|
+
Array [
|
|
311
|
+
Object {
|
|
312
|
+
"flexDirection": "column",
|
|
313
|
+
},
|
|
314
|
+
Object {
|
|
315
|
+
"flex": 1,
|
|
316
|
+
},
|
|
317
|
+
]
|
|
298
318
|
}
|
|
299
319
|
>
|
|
300
320
|
<View
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { FocusableGroupContext } from "./FocusableGroupContext";
|
|
3
|
+
|
|
4
|
+
type ProviderArgs = {
|
|
5
|
+
id: string;
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const FocusableGroupContextProvider = ({
|
|
10
|
+
id,
|
|
11
|
+
children,
|
|
12
|
+
}: ProviderArgs) => (
|
|
13
|
+
<FocusableGroupContext.Provider value={id}>
|
|
14
|
+
{children}
|
|
15
|
+
</FocusableGroupContext.Provider>
|
|
16
|
+
);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React, { useContext } from "react";
|
|
2
|
+
import { Text } from "react-native";
|
|
3
|
+
import { render } from "@testing-library/react-native";
|
|
4
|
+
import { FocusableGroupContextProvider, FocusableGroupContext } from "../";
|
|
5
|
+
|
|
6
|
+
const MockComponent = () => {
|
|
7
|
+
const focusableContext = useContext(FocusableGroupContext) || "default";
|
|
8
|
+
|
|
9
|
+
return <Text testID={focusableContext} />;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
describe("FocusableGroupContextProvider", () => {
|
|
13
|
+
it("should provide focusable context to the wrapped component", () => {
|
|
14
|
+
const { getByTestId } = render(
|
|
15
|
+
<FocusableGroupContextProvider id="testId">
|
|
16
|
+
<MockComponent />
|
|
17
|
+
</FocusableGroupContextProvider>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
expect(getByTestId("testId")).toBeTruthy();
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Text } from "react-native";
|
|
3
|
+
import { render } from "@testing-library/react-native";
|
|
4
|
+
import { withFocusableContext } from "../withFocusableContext";
|
|
5
|
+
import { FocusableGroupContext } from "../FocusableGroupContext";
|
|
6
|
+
|
|
7
|
+
const MockComponent = ({ groupId }: { groupId: string }) => (
|
|
8
|
+
<Text testID={groupId} />
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
const WrappedComponent = withFocusableContext(MockComponent);
|
|
12
|
+
|
|
13
|
+
describe("withFocusableContext HOC", () => {
|
|
14
|
+
it("should provide focusable context to the wrapped component", () => {
|
|
15
|
+
const { getByTestId } = render(<WrappedComponent />, {
|
|
16
|
+
// eslint-disable-next-line react/display-name
|
|
17
|
+
wrapper: ({ children }: { children: React.ReactElement }) => (
|
|
18
|
+
<FocusableGroupContext.Provider value="test">
|
|
19
|
+
{children}
|
|
20
|
+
</FocusableGroupContext.Provider>
|
|
21
|
+
),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
expect(getByTestId("test")).toBeTruthy();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { FocusableGroupContext } from "./FocusableGroupContext";
|
|
3
|
+
import { FocusableGroupContextProvider } from "./FocusableGroupContextProvider";
|
|
4
|
+
|
|
5
|
+
export { FocusableGroupContext, FocusableGroupContextProvider };
|
|
6
|
+
|
|
7
|
+
export const useGroupId = () => React.useContext(FocusableGroupContext);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { FocusableGroupContext } from "./FocusableGroupContext";
|
|
3
|
+
|
|
4
|
+
export const withFocusableContext = (Component) => {
|
|
5
|
+
// eslint-disable-next-line react/display-name
|
|
6
|
+
return ({ groupId, ...props }: Record<string, any>) => (
|
|
7
|
+
<FocusableGroupContext.Consumer>
|
|
8
|
+
{(groupIdContext: string) => {
|
|
9
|
+
// eslint-disable-next-line react/display-name
|
|
10
|
+
const propsGroupId = groupId || null;
|
|
11
|
+
const providedGroupId = propsGroupId || groupIdContext;
|
|
12
|
+
|
|
13
|
+
return <Component {...props} groupId={providedGroupId} />;
|
|
14
|
+
}}
|
|
15
|
+
</FocusableGroupContext.Consumer>
|
|
16
|
+
);
|
|
17
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-ui-components",
|
|
3
|
-
"version": "12.0.0-rc.
|
|
3
|
+
"version": "12.0.0-rc.83",
|
|
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": "12.0.0-rc.
|
|
38
|
-
"@applicaster/zapp-react-native-bridge": "12.0.0-rc.
|
|
39
|
-
"@applicaster/zapp-react-native-redux": "12.0.0-rc.
|
|
40
|
-
"@applicaster/zapp-react-native-utils": "12.0.0-rc.
|
|
37
|
+
"@applicaster/applicaster-types": "12.0.0-rc.83",
|
|
38
|
+
"@applicaster/zapp-react-native-bridge": "12.0.0-rc.83",
|
|
39
|
+
"@applicaster/zapp-react-native-redux": "12.0.0-rc.83",
|
|
40
|
+
"@applicaster/zapp-react-native-utils": "12.0.0-rc.83",
|
|
41
41
|
"promise": "^8.3.0",
|
|
42
42
|
"react-router-native": "^5.1.2",
|
|
43
43
|
"url": "^0.11.0",
|
|
File without changes
|
|
File without changes
|