@momo-kits/foundation 0.160.1-beta.6 → 0.160.1-beta.8

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 (52) hide show
  1. package/Application/BottomSheet.tsx +3 -3
  2. package/Application/BottomTab/BottomTabBar.tsx +17 -17
  3. package/Application/BottomTab/CustomBottomTabItem.tsx +1 -1
  4. package/Application/BottomTab/index.tsx +31 -55
  5. package/Application/Components/BackgroundImageView.tsx +22 -6
  6. package/Application/Components/HeaderAnimated.tsx +32 -29
  7. package/Application/Components/HeaderBackground.tsx +21 -27
  8. package/Application/Components/HeaderExtendHeader.tsx +114 -94
  9. package/Application/Components/HeaderTitle.tsx +40 -11
  10. package/Application/Components/SearchHeader.tsx +17 -22
  11. package/Application/NavigationContainer.tsx +22 -9
  12. package/Application/ScaleSizeProvider.tsx +16 -0
  13. package/Application/WidgetContainer.tsx +6 -1
  14. package/Application/index.ts +2 -0
  15. package/Application/types.ts +10 -4
  16. package/Application/utils.tsx +4 -3
  17. package/Badge/Badge.tsx +3 -9
  18. package/Badge/BadgeDot.tsx +1 -1
  19. package/Badge/BadgeDotAnimation.tsx +53 -71
  20. package/Badge/BadgeRibbon.tsx +1 -1
  21. package/Button/index.tsx +3 -6
  22. package/CheckBox/index.tsx +1 -1
  23. package/Context/index.ts +4 -0
  24. package/Icon/index.tsx +1 -1
  25. package/IconButton/index.tsx +1 -1
  26. package/Image/index.tsx +1 -1
  27. package/Input/Input.tsx +1 -1
  28. package/Input/InputDropDown.tsx +1 -1
  29. package/Input/InputMoney.tsx +1 -1
  30. package/Input/InputOTP.tsx +39 -24
  31. package/Input/InputPhoneNumber.tsx +1 -1
  32. package/Input/InputSearch.tsx +1 -1
  33. package/Input/InputTextArea.tsx +1 -1
  34. package/Layout/FloatingButton.tsx +51 -51
  35. package/Layout/Item.tsx +1 -1
  36. package/Layout/Screen.tsx +61 -57
  37. package/Loader/ProgressBar.tsx +20 -18
  38. package/Pagination/Dot.tsx +2 -2
  39. package/Pagination/PaginationDot.tsx +1 -1
  40. package/Pagination/PaginationNumber.tsx +1 -1
  41. package/Pagination/PaginationScroll.tsx +32 -28
  42. package/Pagination/PaginationWhiteDot.tsx +1 -1
  43. package/Popup/PopupNotify.tsx +1 -1
  44. package/Popup/PopupPromotion.tsx +1 -1
  45. package/Radio/index.tsx +1 -1
  46. package/Skeleton/index.tsx +32 -24
  47. package/Switch/index.tsx +1 -1
  48. package/Tag/index.tsx +1 -1
  49. package/Text/index.tsx +1 -1
  50. package/Text/utils.ts +40 -17
  51. package/Title/index.tsx +1 -1
  52. package/package.json +34 -34
@@ -20,7 +20,7 @@ import { Icon } from '../Icon';
20
20
  import { useHeaderHeight } from '@react-navigation/elements';
21
21
  import Animated, {
22
22
  Easing,
23
- Extrapolate,
23
+ Extrapolation,
24
24
  interpolate,
25
25
  runOnJS,
26
26
  useAnimatedStyle,
@@ -39,7 +39,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
39
39
  const heightHeader = useHeaderHeight();
40
40
  const keyboardOffset = heightHeader - Math.min(insets.bottom, 21);
41
41
 
42
- const showBaseLineDebug = context?.designSystemConfig?.isBaselineEnabled;
42
+ const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
43
43
 
44
44
  const {
45
45
  screen: Screen,
@@ -242,7 +242,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
242
242
  translateY.value,
243
243
  [0, heightDevice],
244
244
  [1, 0],
245
- Extrapolate.CLAMP,
245
+ Extrapolation.CLAMP,
246
246
  ),
247
247
  };
248
248
  });
@@ -2,13 +2,17 @@ import { BottomTabBarProps } from '@react-navigation/bottom-tabs';
2
2
  import { CommonActions, Route } from '@react-navigation/native';
3
3
  import React, { useCallback, useContext } from 'react';
4
4
  import {
5
- Animated,
6
5
  Platform,
7
6
  StyleSheet,
8
7
  TouchableOpacity,
9
8
  useWindowDimensions,
10
9
  View,
11
10
  } from 'react-native';
11
+ import Animated, {
12
+ useAnimatedStyle,
13
+ useSharedValue,
14
+ withTiming,
15
+ } from 'react-native-reanimated';
12
16
  import { EdgeInsets, useSafeAreaInsets } from 'react-native-safe-area-context';
13
17
  import { Colors, Radius, Styles } from '../../Consts';
14
18
  import { Icon } from '../../Icon';
@@ -57,13 +61,18 @@ export default function BottomTabBar({
57
61
  const useFloating = floatingButton && state.routes.length % 2 === 0;
58
62
  const itemWidth = widthDevice / (state.routes.length + (useFloating ? 1 : 0));
59
63
  // const buildLink = useLinkBuilder();
60
- const indicatorAnimated = React.useRef(new Animated.Value(0)).current;
64
+ const indicatorAnimated = useSharedValue(0);
61
65
  const insets = useSafeAreaInsets();
66
+
67
+ const indicatorStyle = useAnimatedStyle(() => ({
68
+ width: itemWidth,
69
+ transform: [{ translateX: indicatorAnimated.value }],
70
+ }));
62
71
  const paddingBottom = getPaddingBottom(insets);
63
72
  const focusedTab = state?.routes[state.index]?.name || routes[0]?.params;
64
73
 
65
74
  const context = useContext<any>(MiniAppContext);
66
- const showBaseLineDebug = context?.designSystemConfig?.isBaselineEnabled;
75
+ const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
67
76
 
68
77
  /**
69
78
  * render tab item
@@ -199,11 +208,7 @@ export default function BottomTabBar({
199
208
  if (useFloating && index > (state.routes.length - 1) / 2) {
200
209
  index += 1;
201
210
  }
202
- Animated.timing(indicatorAnimated, {
203
- toValue: itemWidth * index,
204
- useNativeDriver: true,
205
- duration: 200,
206
- }).start();
211
+ indicatorAnimated.value = withTiming(itemWidth * index, { duration: 200 });
207
212
  }, [
208
213
  state.index,
209
214
  itemWidth,
@@ -232,7 +237,7 @@ export default function BottomTabBar({
232
237
  };
233
238
 
234
239
  return (
235
- <Animated.View
240
+ <View
236
241
  style={[
237
242
  floatingButton ? styles.tabBarFloatingButton : styles.tabBar,
238
243
  {
@@ -250,12 +255,7 @@ export default function BottomTabBar({
250
255
  <View style={styles.content} accessibilityLabel={'bottom_tab_bar'}>
251
256
  {useFloating && floatingButton?.container}
252
257
  <Animated.View
253
- style={{
254
- width: itemWidth,
255
- position: 'absolute',
256
- top: 0,
257
- transform: [{ translateX: indicatorAnimated }],
258
- }}
258
+ style={[{ position: 'absolute', top: 0 }, indicatorStyle]}
259
259
  >
260
260
  <View
261
261
  style={[
@@ -266,7 +266,7 @@ export default function BottomTabBar({
266
266
  </Animated.View>
267
267
  {renderTabBar()}
268
268
  </View>
269
- </Animated.View>
269
+ </View>
270
270
  );
271
271
  }
272
272
 
@@ -299,7 +299,7 @@ const styles = StyleSheet.create({
299
299
  left: 0,
300
300
  right: 0,
301
301
  top: -2,
302
- bottom: Platform.OS === 'ios' ? -6 : 4,
302
+ bottom: Platform.OS === 'ios' ? -6 : 4
303
303
  },
304
304
  floatingContent: {
305
305
  alignItems: 'center',
@@ -61,7 +61,7 @@ const CustomBottomTabItem: React.FC<CustomBottomTabItemProps> = ({
61
61
  allowFontScaling,
62
62
  }) => {
63
63
  const context = useContext<any>(MiniAppContext);
64
- const showBaseLineDebug = context?.designSystemConfig?.isBaselineEnabled;
64
+ const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
65
65
 
66
66
  const renderIcon = () => {
67
67
  if (icon === undefined) {
@@ -5,16 +5,20 @@ import {
5
5
  useFocusEffect,
6
6
  } from '@react-navigation/native';
7
7
  import { createStackNavigator } from '@react-navigation/stack';
8
- import React, { useContext, useEffect, useLayoutEffect, useRef } from 'react';
8
+ import React, { useContext, useEffect, useLayoutEffect } from 'react';
9
9
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
10
10
  import {
11
- Animated,
12
11
  Platform,
13
12
  StatusBar,
14
13
  StyleSheet,
15
14
  useWindowDimensions,
16
15
  View,
17
16
  } from 'react-native';
17
+ import Animated, {
18
+ useAnimatedStyle,
19
+ useSharedValue,
20
+ withTiming,
21
+ } from 'react-native-reanimated';
18
22
  import { Colors } from '../../Consts';
19
23
  import { Icon } from '../../Icon';
20
24
  import { exportFontFamily, Text } from '../../Text';
@@ -35,11 +39,16 @@ const TabScreen: React.FC<any> = ({ route, navigation }) => {
35
39
 
36
40
  const opacityValue = 0.3;
37
41
  const scaleValue = 0.97;
38
- const opacity = useRef(new Animated.Value(opacityValue)).current;
39
- const scale = useRef(new Animated.Value(scaleValue)).current;
42
+ const opacity = useSharedValue(opacityValue);
43
+ const scale = useSharedValue(scaleValue);
40
44
  const screenName = screen?.name || screen?.type?.name || 'Invalid';
41
45
  const { isBackgroundToForeground } = useAppState();
42
46
 
47
+ const tabAnimatedStyle = useAnimatedStyle(() => ({
48
+ opacity: opacity.value,
49
+ transform: [{ scale: scale.value }],
50
+ }));
51
+
43
52
  const onScreenNavigated = (pre: string, current: string) => {
44
53
  if (!isBackgroundToForeground) {
45
54
  const data: any = {
@@ -69,18 +78,8 @@ const TabScreen: React.FC<any> = ({ route, navigation }) => {
69
78
  useFocusEffect(
70
79
  React.useCallback(
71
80
  () => {
72
- Animated.parallel([
73
- Animated.timing(opacity, {
74
- toValue: 1,
75
- duration: 200,
76
- useNativeDriver: true,
77
- }),
78
- Animated.timing(scale, {
79
- toValue: 1,
80
- duration: 200,
81
- useNativeDriver: true,
82
- }),
83
- ]).start();
81
+ opacity.value = withTiming(1, { duration: 200 });
82
+ scale.value = withTiming(1, { duration: 200 });
84
83
 
85
84
  setTimeout(() => {
86
85
  navigator?.maxApi?.getDataObserver?.(
@@ -96,18 +95,8 @@ const TabScreen: React.FC<any> = ({ route, navigation }) => {
96
95
 
97
96
  return () => {
98
97
  if (navigation.getState().index !== route?.params.index) {
99
- Animated.parallel([
100
- Animated.timing(opacity, {
101
- toValue: opacityValue,
102
- duration: 200,
103
- useNativeDriver: true,
104
- }),
105
- Animated.timing(scale, {
106
- toValue: scaleValue,
107
- duration: 200,
108
- useNativeDriver: true,
109
- }),
110
- ]).start();
98
+ opacity.value = withTiming(opacityValue, { duration: 200 });
99
+ scale.value = withTiming(scaleValue, { duration: 200 });
111
100
  }
112
101
  };
113
102
  },
@@ -147,15 +136,7 @@ const TabScreen: React.FC<any> = ({ route, navigation }) => {
147
136
 
148
137
  if (nested) {
149
138
  return (
150
- <Animated.View
151
- style={[
152
- styles.container,
153
- {
154
- opacity,
155
- transform: [{ scale }],
156
- },
157
- ]}
158
- >
139
+ <Animated.View style={[styles.container, tabAnimatedStyle]}>
159
140
  <Stack.Navigator
160
141
  screenOptions={{
161
142
  headerStyle: {
@@ -228,10 +209,15 @@ const BottomTab: React.FC<BottomTabProps> = ({
228
209
  const dimensions = useWindowDimensions();
229
210
  const insets = useSafeAreaInsets();
230
211
  const initialIndex = tabs.findIndex(i => i.name === initialRouteName);
231
- const indicatorAnimated = useRef(new Animated.Value(0));
232
- const activeIndex = useRef(initialIndex > 0 ? initialIndex : 0);
212
+ const indicatorAnimated = useSharedValue(0);
213
+ const activeIndex = React.useRef(initialIndex > 0 ? initialIndex : 0);
233
214
  const itemWidth = dimensions.width / tabs.length;
234
215
 
216
+ const indicatorStyle = useAnimatedStyle(() => ({
217
+ width: itemWidth,
218
+ transform: [{ translateX: indicatorAnimated.value }],
219
+ }));
220
+
235
221
  useLayoutEffect(() => {
236
222
  navigation?.setOptions({
237
223
  headerShown: false,
@@ -241,20 +227,16 @@ const BottomTab: React.FC<BottomTabProps> = ({
241
227
  }, [navigation]);
242
228
 
243
229
  useEffect(() => {
244
- Animated.timing(indicatorAnimated.current, {
245
- toValue: itemWidth * activeIndex.current,
246
- useNativeDriver: true,
230
+ indicatorAnimated.value = withTiming(itemWidth * activeIndex.current, {
247
231
  duration: 200,
248
- }).start();
249
- }, [itemWidth]);
232
+ });
233
+ }, [itemWidth, indicatorAnimated]);
250
234
 
251
235
  const onFocus = (e: any) => {
252
236
  activeIndex.current = tabs.findIndex(i => e.target.includes(i.name));
253
- Animated.timing(indicatorAnimated.current, {
254
- toValue: itemWidth * activeIndex.current,
255
- useNativeDriver: true,
237
+ indicatorAnimated.value = withTiming(itemWidth * activeIndex.current, {
256
238
  duration: 200,
257
- }).start();
239
+ });
258
240
  };
259
241
 
260
242
  const handler: {
@@ -294,13 +276,7 @@ const BottomTab: React.FC<BottomTabProps> = ({
294
276
  ]}
295
277
  >
296
278
  <Animated.View
297
- style={[
298
- styles.indicatorContainer,
299
- {
300
- width: itemWidth,
301
- transform: [{ translateX: indicatorAnimated.current }],
302
- },
303
- ]}
279
+ style={[styles.indicatorContainer, indicatorStyle]}
304
280
  >
305
281
  <View
306
282
  style={[
@@ -1,5 +1,11 @@
1
1
  import React, { FC, useContext } from 'react';
2
- import { Animated, Platform, StyleSheet } from 'react-native';
2
+ import { Platform, StyleSheet } from 'react-native';
3
+ import Animated, {
4
+ Extrapolation,
5
+ interpolate,
6
+ useAnimatedStyle,
7
+ type SharedValue,
8
+ } from 'react-native-reanimated';
3
9
  import { Image } from '../../Image';
4
10
  import { Colors } from '../../Consts';
5
11
  import { ApplicationContext } from '../../Context';
@@ -8,16 +14,26 @@ type BackgroundImageViewProps = {
8
14
  useShadowHeader: boolean;
9
15
  headerBackground?: string;
10
16
  heightHeader: number | `${number}%`;
11
- opacityBackground: Animated.AnimatedInterpolation<any>;
17
+ animatedValue: SharedValue<number>;
12
18
  };
13
19
 
14
20
  const BackgroundImageView: FC<BackgroundImageViewProps> = ({
15
21
  useShadowHeader = true,
16
22
  headerBackground = null,
17
23
  heightHeader,
18
- opacityBackground,
24
+ animatedValue,
19
25
  }) => {
20
26
  const { theme } = useContext(ApplicationContext);
27
+
28
+ const opacityStyle = useAnimatedStyle(() => ({
29
+ opacity: interpolate(
30
+ animatedValue.value,
31
+ [0, 52],
32
+ [0, 1],
33
+ Extrapolation.CLAMP,
34
+ ),
35
+ }));
36
+
21
37
  if (Platform.OS === 'android') {
22
38
  return (
23
39
  <Animated.View
@@ -27,8 +43,8 @@ const BackgroundImageView: FC<BackgroundImageViewProps> = ({
27
43
  {
28
44
  height: heightHeader,
29
45
  backgroundColor: theme.colors.background.surface,
30
- opacity: opacityBackground,
31
46
  },
47
+ opacityStyle,
32
48
  ]}
33
49
  >
34
50
  {headerBackground && (
@@ -51,8 +67,8 @@ const BackgroundImageView: FC<BackgroundImageViewProps> = ({
51
67
  {
52
68
  height: heightHeader,
53
69
  backgroundColor: theme.colors.background.surface,
54
- opacity: opacityBackground,
55
70
  },
71
+ opacityStyle,
56
72
  ]}
57
73
  />
58
74
  <Animated.View
@@ -60,8 +76,8 @@ const BackgroundImageView: FC<BackgroundImageViewProps> = ({
60
76
  styles.hidden,
61
77
  {
62
78
  height: heightHeader,
63
- opacity: opacityBackground,
64
79
  },
80
+ opacityStyle,
65
81
  ]}
66
82
  >
67
83
  {headerBackground && (
@@ -1,46 +1,49 @@
1
- import { Animated, StyleSheet } from 'react-native';
1
+ import { StyleSheet } from 'react-native';
2
+ import Animated, {
3
+ Extrapolation,
4
+ interpolate,
5
+ useAnimatedStyle,
6
+ } from 'react-native-reanimated';
2
7
  import { type HeaderAnimatedProps } from '../types';
3
8
  import React from 'react';
4
9
  import { Image } from '../../Image';
5
10
  import { Colors } from '../../Consts';
6
11
 
7
- /**
8
- * default header banner for header animated
9
- */
10
12
  const HeaderAnimated: React.FC<HeaderAnimatedProps> = ({
11
13
  animatedValue,
12
14
  image,
13
15
  useScale = true,
14
16
  children,
15
17
  }) => {
16
- const scale = useScale
17
- ? animatedValue.interpolate({
18
- inputRange: [-300, 0, 300],
19
- outputRange: [4, 1, 1],
20
- extrapolate: 'clamp',
21
- })
22
- : 1;
23
- const opacity = animatedValue.interpolate({
24
- inputRange: [0, 150, 300],
25
- outputRange: [1, 0.5, 0],
26
- extrapolate: 'clamp',
27
- });
28
- const translateY = animatedValue.interpolate({
29
- inputRange: [-300, 0],
30
- outputRange: [-80, -2],
31
- extrapolate: 'clamp',
18
+ const animatedStyle = useAnimatedStyle(() => {
19
+ const scale = useScale
20
+ ? interpolate(
21
+ animatedValue.value,
22
+ [-300, 0, 300],
23
+ [4, 1, 1],
24
+ Extrapolation.CLAMP,
25
+ )
26
+ : 1;
27
+ const opacity = interpolate(
28
+ animatedValue.value,
29
+ [0, 150, 300],
30
+ [1, 0.5, 0],
31
+ Extrapolation.CLAMP,
32
+ );
33
+ const translateY = interpolate(
34
+ animatedValue.value,
35
+ [-300, 0],
36
+ [-80, -2],
37
+ Extrapolation.CLAMP,
38
+ );
39
+ return {
40
+ opacity,
41
+ transform: [{ scale }, { translateY }],
42
+ };
32
43
  });
33
44
 
34
45
  return (
35
- <Animated.View
36
- style={[
37
- styles.container,
38
- {
39
- opacity: opacity,
40
- transform: [{ scale }, { translateY }],
41
- },
42
- ]}
43
- >
46
+ <Animated.View style={[styles.container, animatedStyle]}>
44
47
  {children ?? (
45
48
  <Image
46
49
  source={{
@@ -1,19 +1,15 @@
1
1
  import LinearGradient from 'react-native-linear-gradient';
2
- import { Animated, StyleSheet, View } from 'react-native';
2
+ import { StyleSheet, View } from 'react-native';
3
3
  import React, { useContext } from 'react';
4
+ import Animated, { useSharedValue } from 'react-native-reanimated';
4
5
  import { HeaderBackgroundProps } from '../types';
5
6
  import { ApplicationContext, MiniAppContext } from '../../Context';
6
7
  import { Colors, Styles } from '../../Consts';
7
8
  import { Image } from '../../Image';
8
9
  import BackgroundImageView from './BackgroundImageView';
9
10
 
10
- const LinearGradientAnimated = Animated.createAnimatedComponent(LinearGradient);
11
-
12
- /**
13
- * header background for default
14
- */
15
11
  const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
16
- animatedValue = new Animated.Value(0),
12
+ animatedValue,
17
13
  useGradient = true,
18
14
  useShadowHeader = true,
19
15
  gradientColor: customGradientColor,
@@ -23,37 +19,35 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
23
19
  const context = useContext<any>(MiniAppContext);
24
20
  const gradientColor = customGradientColor ?? theme.colors.gradient;
25
21
  const headerImage = headerBackground ?? theme.assets?.headerBackground;
22
+ const fallback = useSharedValue(0);
23
+ const sv = animatedValue ?? fallback;
26
24
 
27
- const showBaseLineDebug = context?.designSystemConfig?.isBaselineEnabled;
28
-
29
- const opacityBackground = animatedValue?.interpolate({
30
- inputRange: [0, 52],
31
- outputRange: [0, 1],
32
- extrapolate: 'clamp',
33
- });
25
+ const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
34
26
 
35
27
  return (
36
28
  <View style={[Styles.flex, showBaseLineDebug && styles.debugBaseLine]}>
37
29
  <BackgroundImageView
38
30
  useShadowHeader={useShadowHeader}
39
31
  heightHeader={'100%'}
40
- opacityBackground={opacityBackground}
32
+ animatedValue={sv}
41
33
  headerBackground={headerImage}
42
34
  />
43
35
  <View style={styles.gradientContainer}>
44
36
  {useGradient && !!gradientColor && (
45
- <LinearGradientAnimated
46
- colors={[gradientColor, gradientColor + '00']}
47
- style={styles.extendedHeader}
48
- >
49
- {!!headerImage && (
50
- <Image
51
- style={styles.headerBackground}
52
- source={{ uri: headerImage }}
53
- loading={false}
54
- />
55
- )}
56
- </LinearGradientAnimated>
37
+ <Animated.View style={styles.extendedHeader}>
38
+ <LinearGradient
39
+ colors={[gradientColor, gradientColor + '00']}
40
+ style={StyleSheet.absoluteFill}
41
+ >
42
+ {!!headerImage && (
43
+ <Image
44
+ style={styles.headerBackground}
45
+ source={{ uri: headerImage }}
46
+ loading={false}
47
+ />
48
+ )}
49
+ </LinearGradient>
50
+ </Animated.View>
57
51
  )}
58
52
  </View>
59
53
  </View>