@applicaster/zapp-react-native-ui-components 15.0.0-rc.4 → 15.0.0-rc.40

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 (43) hide show
  1. package/Components/AnimatedInOut/index.tsx +69 -26
  2. package/Components/Cell/Cell.tsx +8 -3
  3. package/Components/Cell/FocusableWrapper.tsx +44 -0
  4. package/Components/Cell/TvOSCellComponent.tsx +92 -17
  5. package/Components/HandlePlayable/HandlePlayable.tsx +14 -65
  6. package/Components/HandlePlayable/const.ts +3 -0
  7. package/Components/HandlePlayable/utils.ts +74 -0
  8. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +16 -1
  9. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +36 -2
  10. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +10 -6
  11. package/Components/MasterCell/DefaultComponents/Text/index.tsx +8 -8
  12. package/Components/MasterCell/index.tsx +2 -0
  13. package/Components/PlayerContainer/PlayerContainer.tsx +1 -16
  14. package/Components/PlayerImageBackground/index.tsx +3 -22
  15. package/Components/Screen/TV/hooks/useInitialFocus.ts +14 -4
  16. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +2 -0
  17. package/Components/Screen/index.tsx +22 -5
  18. package/Components/ScreenRevealManager/ScreenRevealManager.ts +40 -8
  19. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +86 -69
  20. package/Components/ScreenRevealManager/utils/index.ts +23 -0
  21. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +54 -24
  22. package/Components/Tabs/TV/Tabs.tsx +20 -3
  23. package/Components/Transitioner/Scene.tsx +15 -2
  24. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -0
  25. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +114 -171
  26. package/Components/VideoModal/ModalAnimation/index.ts +2 -13
  27. package/Components/VideoModal/ModalAnimation/utils.ts +1 -327
  28. package/Components/VideoModal/PlayerWrapper.tsx +14 -88
  29. package/Components/VideoModal/VideoModal.tsx +1 -5
  30. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -0
  31. package/Components/VideoModal/hooks/useModalSize.ts +10 -5
  32. package/Components/VideoModal/playerWrapperStyle.ts +70 -0
  33. package/Components/VideoModal/playerWrapperUtils.ts +91 -0
  34. package/Components/VideoModal/utils.ts +7 -0
  35. package/index.d.ts +7 -0
  36. package/package.json +5 -5
  37. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +0 -60
  38. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +0 -417
  39. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.web.tsx +0 -294
  40. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +0 -176
  41. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.web.tsx +0 -93
  42. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +0 -500
  43. package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +0 -108
@@ -4,6 +4,7 @@ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
4
4
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
5
5
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks/device/useIsTablet";
6
6
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
7
+ import { create } from "zustand";
7
8
 
8
9
  export const useConfiguration = () => {
9
10
  const {
@@ -52,6 +53,12 @@ export const useConfiguration = () => {
52
53
  };
53
54
  };
54
55
 
56
+ export const useAnimationStateStore = create<{
57
+ isAnimationInProgress: boolean;
58
+ }>(() => ({
59
+ isAnimationInProgress: false,
60
+ }));
61
+
55
62
  const fullSize = {
56
63
  width: "100%",
57
64
  height: "100%",
package/index.d.ts CHANGED
@@ -228,6 +228,12 @@ declare type TabsSelectionContextType = {
228
228
  selectedEntryIndex: number;
229
229
  };
230
230
 
231
+ declare type TabsAccessibility = {
232
+ announcement?: string;
233
+ selectedHint?: string;
234
+ hint?: string;
235
+ };
236
+
231
237
  declare type TabsProps = {
232
238
  entry: ZappEntry[];
233
239
  groupId: string;
@@ -235,6 +241,7 @@ declare type TabsProps = {
235
241
  focused?: boolean;
236
242
  parentFocus?: ParentFocus;
237
243
  style?: ReactViewStyle;
244
+ accessibility?: TabsAccessibility;
238
245
  };
239
246
 
240
247
  declare type TabContentProps = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-ui-components",
3
- "version": "15.0.0-rc.4",
3
+ "version": "15.0.0-rc.40",
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",
@@ -28,10 +28,10 @@
28
28
  },
29
29
  "homepage": "https://github.com/applicaster/quickbrick#readme",
30
30
  "dependencies": {
31
- "@applicaster/applicaster-types": "15.0.0-rc.4",
32
- "@applicaster/zapp-react-native-bridge": "15.0.0-rc.4",
33
- "@applicaster/zapp-react-native-redux": "15.0.0-rc.4",
34
- "@applicaster/zapp-react-native-utils": "15.0.0-rc.4",
31
+ "@applicaster/applicaster-types": "15.0.0-rc.40",
32
+ "@applicaster/zapp-react-native-bridge": "15.0.0-rc.40",
33
+ "@applicaster/zapp-react-native-redux": "15.0.0-rc.40",
34
+ "@applicaster/zapp-react-native-utils": "15.0.0-rc.40",
35
35
  "promise": "^8.3.0",
36
36
  "url": "^0.11.0",
37
37
  "uuid": "^3.3.2"
@@ -1,60 +0,0 @@
1
- import React from "react";
2
- import { Animated, ViewStyle } from "react-native";
3
-
4
- import {
5
- useModalAnimationContext,
6
- PlayerAnimationStateEnum,
7
- } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
8
-
9
- type Props = {
10
- style: ViewStyle[];
11
- children: React.ReactNode;
12
- };
13
-
14
- export const AnimatedPlayerModalWrapper = (props: Props) => {
15
- const {
16
- playerAnimationState,
17
- animatedValues: { lastScrollY, dragScrollY, translateYOffset },
18
- modalSnapPoints,
19
- setStartComponentsAnimation,
20
- } = useModalAnimationContext();
21
-
22
- const interpolateConfig: Animated.InterpolationConfigType = React.useMemo(
23
- () => ({
24
- inputRange: modalSnapPoints,
25
- outputRange: modalSnapPoints,
26
- extrapolate: "clamp",
27
- }),
28
- [modalSnapPoints]
29
- );
30
-
31
- let translateY;
32
-
33
- if (playerAnimationState === PlayerAnimationStateEnum.drag_player) {
34
- translateY = translateYOffset.interpolate(interpolateConfig);
35
- } else {
36
- const reverseLastScrollY = Animated.multiply(
37
- new Animated.Value(-1),
38
- lastScrollY
39
- );
40
-
41
- translateY = Animated.add(
42
- translateYOffset,
43
- Animated.add(dragScrollY, reverseLastScrollY)
44
- ).interpolate(interpolateConfig);
45
- }
46
-
47
- React.useEffect(() => {
48
- (playerAnimationState === PlayerAnimationStateEnum.minimize ||
49
- playerAnimationState === PlayerAnimationStateEnum.maximize) &&
50
- setStartComponentsAnimation(true);
51
- }, [playerAnimationState]);
52
-
53
- return (
54
- <Animated.View
55
- style={[props.style, { transform: [{ translateY: translateY }] }]}
56
- >
57
- {props.children}
58
- </Animated.View>
59
- );
60
- };
@@ -1,417 +0,0 @@
1
- import React from "react";
2
- import { Animated, StyleSheet, View } from "react-native";
3
-
4
- import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
5
- import {
6
- NativeViewGestureHandler,
7
- PanGestureHandler,
8
- State,
9
- TapGestureHandler,
10
- } from "react-native-gesture-handler";
11
-
12
- import { PlayerContainerContext } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainerContext";
13
- import {
14
- PlayerAnimationStateEnum,
15
- useModalAnimationContext,
16
- } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
17
- import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
18
- import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
19
-
20
- import {
21
- resetScrollAnimatedValues,
22
- setScrollModalAnimatedValue,
23
- } from "./utils";
24
-
25
- import { DURATION_TO_MINIMIZE } from "./const";
26
-
27
- const getAnimatedConfig = (toValue) => {
28
- return {
29
- toValue,
30
- duration: DURATION_TO_MINIMIZE,
31
- useNativeDriver: true,
32
- };
33
- };
34
-
35
- const generalStyles = StyleSheet.create({
36
- container: {
37
- flex: 1,
38
- },
39
- });
40
-
41
- type Props = {
42
- children: React.ReactNode;
43
- };
44
-
45
- const activeOffsetY = [-5, 5] as [number, number];
46
-
47
- export const AnimatedScrollModalComponent = ({ children }: Props) => {
48
- const {
49
- isActiveGesture,
50
- playerAnimationState,
51
- setPlayerAnimationState,
52
- resetPlayerAnimationState,
53
- animatedValues: {
54
- lastScrollY,
55
- dragScrollY,
56
- dragVideoPlayerY,
57
- translateYOffset,
58
- },
59
- lastScrollYValue,
60
- scrollPosition,
61
- modalSnapPoints,
62
- lastSnap,
63
- setLastSnap,
64
- setStartComponentsAnimation,
65
- } = useModalAnimationContext();
66
-
67
- const [enableGesture, setIEnableGesture] = React.useState<boolean>(true);
68
-
69
- const { isLanguageOverlayVisible, isSeekBarTouch } = React.useContext(
70
- PlayerContainerContext
71
- );
72
-
73
- const { maximiseVideoModal, minimiseVideoModal, videoModalState } =
74
- useNavigation();
75
-
76
- const {
77
- mode: videoModalMode,
78
- previousMode: previousVideoModalMode,
79
- item: videoModalItem,
80
- } = videoModalState;
81
-
82
- const isMaximizedModal: boolean = videoModalMode === "MAXIMIZED";
83
- const isMinimizedModal: boolean = videoModalMode === "MINIMIZED";
84
- const previousItemId = usePrevious(videoModalItem?.id);
85
-
86
- const isNotMinimizeMaximazeAnimation =
87
- playerAnimationState !== PlayerAnimationStateEnum.minimize &&
88
- playerAnimationState !== PlayerAnimationStateEnum.maximize;
89
-
90
- const isEnablePanGesture =
91
- enableGesture &&
92
- !isLanguageOverlayVisible &&
93
- isNotMinimizeMaximazeAnimation &&
94
- !isSeekBarTouch &&
95
- (isMaximizedModal || isMinimizedModal);
96
-
97
- const isAudioItem = React.useMemo(
98
- () =>
99
- videoModalItem?.content?.type?.includes?.("audio") ||
100
- videoModalItem?.type?.value === "audio",
101
- [videoModalItem]
102
- );
103
-
104
- // Refs for components
105
- const scrollRef = React.useRef(null);
106
- const tapHandlerRef = React.useRef(null);
107
- const panHandlerRef = React.useRef(null);
108
-
109
- const onRegisterLastScroll = Animated.event(
110
- [{ nativeEvent: { contentOffset: { y: lastScrollY } } }],
111
- { useNativeDriver: true }
112
- );
113
-
114
- const onGestureEvent = Animated.event(
115
- [{ nativeEvent: { translationY: dragScrollY } }],
116
- { useNativeDriver: true }
117
- );
118
-
119
- const onHandlerStateChange = React.useCallback(
120
- ({ nativeEvent }) => {
121
- if (
122
- nativeEvent.oldState === State.ACTIVE &&
123
- scrollPosition.current === 0
124
- ) {
125
- // eslint-disable-next-line prefer-const
126
- const { velocityY, translationY } = nativeEvent;
127
- const dragToss = 0.05;
128
-
129
- const preparedTranslationY =
130
- Math.abs(translationY) - lastScrollYValue.current;
131
-
132
- if (isMaximizedModal) {
133
- const endOffsetY =
134
- lastSnap + preparedTranslationY + dragToss * velocityY + 150;
135
-
136
- let destSnapPoint = modalSnapPoints[0];
137
-
138
- for (const snapPoint of modalSnapPoints) {
139
- const distFromSnap = Math.abs(snapPoint - endOffsetY);
140
-
141
- if (distFromSnap < Math.abs(destSnapPoint - endOffsetY)) {
142
- destSnapPoint = snapPoint;
143
- }
144
- }
145
-
146
- setLastSnap(destSnapPoint);
147
-
148
- if (destSnapPoint === modalSnapPoints[0]) {
149
- translateYOffset.extractOffset();
150
- translateYOffset.setValue(preparedTranslationY);
151
- translateYOffset.flattenOffset();
152
- dragScrollY.setValue(0);
153
-
154
- setPlayerAnimationState(PlayerAnimationStateEnum.maximize);
155
- } else if (destSnapPoint !== modalSnapPoints[0] && isMaximizedModal) {
156
- setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
157
- }
158
- } else {
159
- if (translationY < 0) {
160
- // from mini to full
161
- setLastSnap(modalSnapPoints[0]);
162
-
163
- translateYOffset.setValue(
164
- modalSnapPoints[1] - preparedTranslationY
165
- );
166
-
167
- dragScrollY.setValue(0);
168
-
169
- setPlayerAnimationState(PlayerAnimationStateEnum.maximize);
170
- } else {
171
- resetPlayerAnimationState();
172
- }
173
- }
174
- } else {
175
- playerAnimationState === PlayerAnimationStateEnum.drag_scroll &&
176
- resetPlayerAnimationState();
177
- }
178
- },
179
- [
180
- lastSnap,
181
- modalSnapPoints,
182
- playerAnimationState,
183
- isMinimizedModal,
184
- isMaximizedModal,
185
- ]
186
- );
187
-
188
- const onScroll = React.useCallback(({ nativeEvent }) => {
189
- scrollPosition.current = nativeEvent.contentOffset.y;
190
- }, []);
191
-
192
- // Workaround for onMomentumScrollEnd issue
193
- // https://github.com/facebook/react-native/issues/32696#issuecomment-1104217223
194
- const canMomentum = React.useRef(false);
195
-
196
- const onMomentumScrollBegin = React.useCallback(() => {
197
- canMomentum.current = true;
198
- }, []);
199
-
200
- const onMomentumScrollEnd = React.useCallback(
201
- ({ nativeEvent }) => {
202
- if (canMomentum.current && !isActiveGesture) {
203
- if (nativeEvent.contentOffset.y === 0) {
204
- resetScrollAnimatedValues(
205
- lastScrollY,
206
- lastScrollYValue,
207
- dragScrollY,
208
- dragVideoPlayerY
209
- );
210
-
211
- setIEnableGesture(true);
212
- } else {
213
- setIEnableGesture(false);
214
- }
215
-
216
- canMomentum.current = false;
217
- }
218
- },
219
- [isActiveGesture]
220
- );
221
-
222
- React.useEffect(() => {
223
- return () => {
224
- scrollPosition.current = 0;
225
-
226
- resetScrollAnimatedValues(
227
- lastScrollY,
228
- lastScrollYValue,
229
- dragScrollY,
230
- dragVideoPlayerY
231
- );
232
- };
233
- }, []);
234
-
235
- React.useEffect(() => {
236
- if (
237
- videoModalMode === "MAXIMIZED" &&
238
- !enableGesture &&
239
- scrollPosition.current === 0
240
- ) {
241
- setIEnableGesture(true);
242
- }
243
-
244
- if (
245
- videoModalMode === "MINIMIZED" &&
246
- previousVideoModalMode === "MAXIMIZED"
247
- ) {
248
- // set animation to the minimize values if moving from the player to another screen
249
- if (playerAnimationState === null) {
250
- setScrollModalAnimatedValue(
251
- translateYOffset,
252
- modalSnapPoints[1],
253
- setLastSnap
254
- );
255
-
256
- resetScrollAnimatedValues(
257
- lastScrollY,
258
- lastScrollYValue,
259
- dragScrollY,
260
- dragVideoPlayerY
261
- );
262
- }
263
- } else if (
264
- playerAnimationState === null &&
265
- ((previousItemId === videoModalItem?.id &&
266
- videoModalMode === "MAXIMIZED" &&
267
- (previousVideoModalMode === "MINIMIZED" ||
268
- previousVideoModalMode === "MAXIMIZED")) ||
269
- (previousItemId !== videoModalItem?.id &&
270
- videoModalMode !== "FULLSCREEN"))
271
- ) {
272
- setPlayerAnimationState(PlayerAnimationStateEnum.maximize);
273
- }
274
- }, [videoModalMode, previousVideoModalMode, videoModalItem]);
275
-
276
- React.useEffect(() => {
277
- if (playerAnimationState === PlayerAnimationStateEnum.minimize) {
278
- if (
279
- (scrollPosition.current === 0 &&
280
- (lastScrollY as any)._value !== 0 &&
281
- (dragScrollY as any)._value === 0 &&
282
- (dragVideoPlayerY as any)._value === 0) ||
283
- (scrollPosition.current !== 0 &&
284
- ((dragScrollY as any)._value !== 0 ||
285
- (dragVideoPlayerY as any)._value !== 0))
286
- ) {
287
- resetScrollAnimatedValues(
288
- lastScrollY,
289
- lastScrollYValue,
290
- dragScrollY,
291
- dragVideoPlayerY
292
- );
293
- }
294
-
295
- Animated.timing(
296
- translateYOffset,
297
- getAnimatedConfig(modalSnapPoints[1])
298
- ).start(() => {
299
- minimiseVideoModal();
300
-
301
- setScrollModalAnimatedValue(
302
- translateYOffset,
303
- modalSnapPoints[1],
304
- setLastSnap
305
- );
306
-
307
- resetScrollAnimatedValues(
308
- lastScrollY,
309
- lastScrollYValue,
310
- dragScrollY,
311
- dragVideoPlayerY
312
- );
313
-
314
- resetPlayerAnimationState();
315
- });
316
- } else if (playerAnimationState === PlayerAnimationStateEnum.maximize) {
317
- Animated.timing(translateYOffset, getAnimatedConfig(0)).start(() => {
318
- maximiseVideoModal();
319
- setScrollModalAnimatedValue(translateYOffset, 0, setLastSnap);
320
-
321
- resetScrollAnimatedValues(
322
- lastScrollY,
323
- lastScrollYValue,
324
- dragScrollY,
325
- dragVideoPlayerY
326
- );
327
-
328
- resetPlayerAnimationState();
329
- });
330
- }
331
- }, [playerAnimationState]);
332
-
333
- React.useEffect(() => {
334
- const lastScrollYListenerId = lastScrollY.addListener(({ value }) => {
335
- lastScrollYValue.current = value;
336
- });
337
-
338
- const dragListenerId = dragScrollY.addListener(({ value }) => {
339
- const preparedValue =
340
- isMinimizedModal && value >= 0
341
- ? 0
342
- : Math.round(isAudioItem ? Math.abs(value) : value);
343
-
344
- if (
345
- preparedValue > 0 &&
346
- scrollPosition.current === 0 &&
347
- playerAnimationState !== PlayerAnimationStateEnum.drag_player &&
348
- playerAnimationState !== PlayerAnimationStateEnum.drag_scroll
349
- ) {
350
- isMinimizedModal && setStartComponentsAnimation(true);
351
- setPlayerAnimationState(PlayerAnimationStateEnum.drag_scroll);
352
- }
353
- });
354
-
355
- return () => {
356
- lastScrollY.removeListener(lastScrollYListenerId);
357
- dragScrollY.removeListener(dragListenerId);
358
- };
359
- }, [playerAnimationState, isAudioItem, isMinimizedModal]);
360
-
361
- const scrollEnabled = isMaximizedModal && isNotMinimizeMaximazeAnimation;
362
-
363
- return (
364
- <View style={generalStyles.container}>
365
- <TapGestureHandler
366
- maxDurationMs={100000}
367
- ref={tapHandlerRef}
368
- maxDeltaY={lastSnap - modalSnapPoints[0]}
369
- numberOfTaps={1}
370
- >
371
- <View pointerEvents="box-none">
372
- <PanGestureHandler
373
- enabled={isEnablePanGesture}
374
- ref={panHandlerRef}
375
- simultaneousHandlers={[scrollRef, tapHandlerRef]}
376
- shouldCancelWhenOutside={isMaximizedModal}
377
- activeOffsetY={activeOffsetY}
378
- onGestureEvent={onGestureEvent}
379
- onHandlerStateChange={onHandlerStateChange}
380
- >
381
- <Animated.View>
382
- <NativeViewGestureHandler
383
- ref={scrollRef}
384
- waitFor={tapHandlerRef}
385
- simultaneousHandlers={panHandlerRef}
386
- >
387
- <Animated.ScrollView
388
- scrollEnabled={scrollEnabled}
389
- bounces={false}
390
- onScrollBeginDrag={onRegisterLastScroll}
391
- onScroll={onScroll}
392
- onMomentumScrollBegin={onMomentumScrollBegin}
393
- onMomentumScrollEnd={onMomentumScrollEnd}
394
- scrollEventThrottle={1}
395
- showsVerticalScrollIndicator={false}
396
- >
397
- {children}
398
- </Animated.ScrollView>
399
- </NativeViewGestureHandler>
400
- </Animated.View>
401
- </PanGestureHandler>
402
- </View>
403
- </TapGestureHandler>
404
- </View>
405
- );
406
- };
407
-
408
- export const AnimatedScrollModal = ({ children }: Props) => {
409
- const {
410
- videoModalState: { visible },
411
- } = useNavigation();
412
-
413
- const Component =
414
- !isTV() && visible ? AnimatedScrollModalComponent : React.Fragment;
415
-
416
- return <Component>{children}</Component>;
417
- };