@momo-kits/foundation 0.115.3-beta.4 → 0.115.3-beta.6

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.
@@ -1,23 +1,32 @@
1
- import React, {useCallback, useContext, useEffect, useRef} from 'react';
1
+ import React, {
2
+ useCallback,
3
+ useContext,
4
+ useEffect,
5
+ useRef,
6
+ useState,
7
+ } from 'react';
2
8
  import {
3
9
  Dimensions,
10
+ Keyboard,
4
11
  KeyboardAvoidingView,
12
+ LayoutAnimation,
5
13
  Modal,
6
14
  PanResponder,
7
15
  Platform,
8
16
  Pressable,
17
+ ScrollView,
9
18
  StyleSheet,
10
19
  TouchableOpacity,
11
20
  View,
12
21
  } from 'react-native';
13
22
  import {useSafeAreaInsets} from 'react-native-safe-area-context';
23
+ import Animated, {Easing, Extrapolate} from 'react-native-reanimated';
24
+ import {useHeaderHeight} from '@react-navigation/stack';
14
25
  import {ApplicationContext} from './index';
15
26
  import {BottomSheetParams} from './types';
16
27
  import {Colors, Radius, Spacing, Styles} from '../Consts';
17
28
  import {Text} from '../Text';
18
29
  import {Icon} from '../Icon';
19
- import {useHeaderHeight} from '@react-navigation/stack';
20
- import Animated, {Easing, Extrapolate} from 'react-native-reanimated';
21
30
 
22
31
  const BottomSheet: React.FC<BottomSheetParams> = props => {
23
32
  const {theme, navigator} = useContext(ApplicationContext);
@@ -25,6 +34,8 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
25
34
  const action = useRef<undefined | string>();
26
35
  const insets = useSafeAreaInsets();
27
36
  const heightHeader = useHeaderHeight();
37
+ const [keyboardHeight, setKeyboardHeight] = useState(0);
38
+ const [contentHeight, setContentHeight] = useState(0);
28
39
  const keyboardOffset = heightHeader - Math.min(insets.bottom, 21);
29
40
 
30
41
  const {
@@ -36,6 +47,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
36
47
  draggable = true,
37
48
  useBottomInset = true,
38
49
  useKeyboardAvoidingView = true,
50
+ useScrollOverflow = false,
39
51
  keyboardVerticalOffset,
40
52
  }: BottomSheetParams = props.route.params;
41
53
 
@@ -86,14 +98,39 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
86
98
  ).current;
87
99
 
88
100
  let Container: any = View;
101
+ let Content: any = View;
89
102
  if (useNativeModal) {
90
103
  Container = Modal;
91
104
  }
105
+ if (useScrollOverflow) {
106
+ Content = ScrollView;
107
+ }
92
108
  let backgroundColor = theme.colors.background.default;
93
109
  if (surface) {
94
110
  backgroundColor = theme.colors.background.surface;
95
111
  }
96
112
 
113
+ const maxContentSize = heightDevice - 52 - keyboardHeight;
114
+
115
+ useEffect(() => {
116
+ const onKeyboardShow = (e: any) => {
117
+ LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
118
+ setKeyboardHeight(e.endCoordinates.height);
119
+ };
120
+ const onKeyboardHide = () => {
121
+ LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
122
+ setKeyboardHeight(0);
123
+ };
124
+
125
+ const showSub = Keyboard.addListener('keyboardWillShow', onKeyboardShow);
126
+ const hideSub = Keyboard.addListener('keyboardWillHide', onKeyboardHide);
127
+
128
+ return () => {
129
+ showSub.remove();
130
+ hideSub.remove();
131
+ };
132
+ }, []);
133
+
97
134
  /**
98
135
  * emit dismiss event
99
136
  */
@@ -105,6 +142,17 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
105
142
  };
106
143
  }, []);
107
144
 
145
+ /**
146
+ * handle content bottom sheet change
147
+ * @param width
148
+ * @param height
149
+ */
150
+ const handleContentSizeChange = (width: number, height: number) => {
151
+ if (contentHeight !== height) {
152
+ setContentHeight(height);
153
+ }
154
+ };
155
+
108
156
  /**
109
157
  * handler dismiss
110
158
  */
@@ -216,9 +264,13 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
216
264
  <Animated.View
217
265
  style={{
218
266
  transform: [{translateY}],
267
+ maxHeight: maxContentSize,
219
268
  }}>
220
269
  {renderHeader()}
221
- <View style={{backgroundColor: backgroundColor}}>
270
+ <Content
271
+ scrollEnabled={contentHeight + 20 > maxContentSize}
272
+ style={{backgroundColor: backgroundColor}}
273
+ onContentSizeChange={handleContentSizeChange}>
222
274
  <Screen
223
275
  {...props}
224
276
  {...props.route.params}
@@ -227,7 +279,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
227
279
  {useBottomInset && (
228
280
  <View style={{height: Math.min(insets.bottom, 21)}} />
229
281
  )}
230
- </View>
282
+ </Content>
231
283
  </Animated.View>
232
284
  </KeyboardAvoidingView>
233
285
  </Container>
@@ -50,6 +50,7 @@ const HeaderRight: React.FC<any> = props => {
50
50
  const HeaderToolkitAction: React.FC<any> = ({
51
51
  tintColor,
52
52
  preventClose,
53
+ useSystemTools = true,
53
54
  useShortcut = false,
54
55
  useMore = false,
55
56
  tools = [],
@@ -198,6 +199,7 @@ const HeaderToolkitAction: React.FC<any> = ({
198
199
  navigator?.maxApi?.dispatchFunction?.(
199
200
  'showTools',
200
201
  {
202
+ useSystemTools,
201
203
  tools,
202
204
  context,
203
205
  },
@@ -98,6 +98,7 @@ export type Tool = {
98
98
  name: {vi: string; en: string};
99
99
  key: string;
100
100
  showBadge?: boolean;
101
+ showRightIcon?: boolean;
101
102
  onPress: () => void;
102
103
  };
103
104
 
@@ -150,6 +151,7 @@ export type BottomSheetParams = {
150
151
  useBottomInset?: boolean;
151
152
  useKeyboardAvoidingView?: boolean;
152
153
  keyboardVerticalOffset?: number;
154
+ useScrollOverflow?: boolean;
153
155
  };
154
156
 
155
157
  export interface NavigationButtonProps extends TouchableOpacityProps {
package/Divider/index.tsx CHANGED
@@ -1,43 +1,19 @@
1
1
  import React, {useContext} from 'react';
2
- import {View, ViewStyle} from 'react-native';
2
+ import {View} from 'react-native';
3
3
  import {ApplicationContext} from '../Application';
4
4
  import {Spacing} from '../Consts';
5
- import {DashDivider} from './DashDivider';
6
5
 
7
- export interface DividerProps {
8
- /**
9
- * Custom styles for divider
10
- */
11
- style?: ViewStyle;
12
-
13
- /**
14
- * Enable margin vertical 4px
15
- */
16
- useMargin?: boolean;
17
-
18
- type?: 'dash' | 'default';
19
- }
20
-
21
- const Divider: React.FC<DividerProps> = ({
22
- style,
23
- useMargin = true,
24
- type = 'default',
25
- }) => {
6
+ const Divider = () => {
26
7
  const {theme} = useContext(ApplicationContext);
27
8
 
28
- if (type === 'dash') return <DashDivider style={style} />;
29
-
30
9
  return (
31
10
  <View
32
- style={[
33
- style,
34
- {
35
- height: 1,
36
- width: '100%',
37
- backgroundColor: theme.colors.border.default,
38
- marginVertical: useMargin ? Spacing.XS : 0,
39
- },
40
- ]}
11
+ style={{
12
+ height: 1,
13
+ width: '100%',
14
+ backgroundColor: theme.colors.border.default,
15
+ marginVertical: Spacing.XS,
16
+ }}
41
17
  />
42
18
  );
43
19
  };
@@ -97,10 +97,10 @@ const InputMoney = forwardRef(
97
97
  };
98
98
 
99
99
  const onClearText = () => {
100
+ inputRef?.current?.clear();
100
101
  setDisplayValue('');
101
102
  setNumericValue('');
102
103
  onChangeText?.('');
103
- inputRef?.current?.focus();
104
104
  };
105
105
 
106
106
  const _onChangeText = (text: string) => {
@@ -113,7 +113,8 @@ const InputMoney = forwardRef(
113
113
 
114
114
  if (text.length < lastDisplayValue.length) {
115
115
  const lastChar = lastDisplayValue.charAt(lastDisplayValue.length - 1);
116
- const isRemovingCurrency = lastDisplayValue.endsWith(currency) || lastChar === ' ';
116
+ const isRemovingCurrency =
117
+ lastDisplayValue.endsWith(currency) || lastChar === ' ';
117
118
  const isRemovingDot = lastChar === '.';
118
119
 
119
120
  if (isRemovingCurrency || isRemovingDot) {
@@ -12,6 +12,7 @@ import {
12
12
  NativeSyntheticEvent,
13
13
  TextInput,
14
14
  TextInputFocusEventData,
15
+ TouchableOpacity,
15
16
  View,
16
17
  } from 'react-native';
17
18
  import {
@@ -24,6 +25,7 @@ import {scaleSize, Text} from '../Text';
24
25
  import {ErrorView, getBorderColor} from './common';
25
26
  import {CaretProps, InputOTPProps} from './index';
26
27
  import styles from './styles';
28
+ import {Icon} from "../Icon";
27
29
 
28
30
  const OTPCaret: FC<CaretProps> = ({index, length}) => {
29
31
  const DURATION = 300;
@@ -132,6 +134,10 @@ const InputOTP = forwardRef(
132
134
  onChangeText?.(text);
133
135
  };
134
136
 
137
+ const onClearText = () => {
138
+ _onChangeText('');
139
+ };
140
+
135
141
  const renderInputs = (inputLength: number) => {
136
142
  const TextInputs: React.ReactNode[] = [];
137
143
  for (let i = 0; i < inputLength; i++) {
@@ -215,6 +221,11 @@ const InputOTP = forwardRef(
215
221
  </Text>
216
222
  </View>
217
223
  )}
224
+ {value.length > 0 && focused && (
225
+ <TouchableOpacity onPress={onClearText} style={styles.clearIcon}>
226
+ <Icon source={'24_navigation_close_circle_full'} size={12} />
227
+ </TouchableOpacity>
228
+ )}
218
229
  <View style={styles.otpInputsView}>
219
230
  {length ? renderInputs(length) : renderUnidentifiedInputs()}
220
231
  </View>
package/Input/styles.ts CHANGED
@@ -150,8 +150,14 @@ export default StyleSheet.create({
150
150
  otpInput: {
151
151
  height: 56,
152
152
  borderRadius: Radius.S,
153
+ justifyContent: 'center',
153
154
  borderWidth: 1,
154
155
  },
156
+ clearIcon: {
157
+ position: 'absolute',
158
+ right: Spacing.M,
159
+ zIndex: 4,
160
+ },
155
161
  otpFloatingView: {
156
162
  position: 'absolute',
157
163
  top: -Spacing.M + 2,
package/Text/utils.ts CHANGED
@@ -1,15 +1,24 @@
1
- import {Dimensions} from 'react-native';
1
+ import {Dimensions, PixelRatio} from 'react-native';
2
2
 
3
3
  const deviceWidth = Dimensions.get('window').width;
4
4
  const DEFAULT_SCREEN_SIZE = 375;
5
+ const MAX_FONT_SCALE = 1.3;
6
+ const MAX_DEVICE_SCALE = 5;
7
+
5
8
  const scaleSize = (size: number) => {
6
- const scaleRate = deviceWidth / DEFAULT_SCREEN_SIZE;
9
+ const fontScale = PixelRatio.getFontScale();
10
+ const deviceScale = deviceWidth / DEFAULT_SCREEN_SIZE;
11
+ let fontSize = size;
12
+
13
+ if (deviceScale > 1) {
14
+ fontSize = Math.min(fontSize * deviceScale, fontSize + MAX_DEVICE_SCALE);
15
+ }
7
16
 
8
- if (scaleRate > 1) {
9
- return Math.min(Math.round(size * scaleRate), size + 3);
17
+ if (fontScale > 1) {
18
+ fontSize = Math.min(fontSize * fontScale, fontSize * MAX_FONT_SCALE);
10
19
  }
11
20
 
12
- return size;
21
+ return fontSize;
13
22
  };
14
23
 
15
24
  export {scaleSize};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/foundation",
3
- "version": "0.115.3-beta.4",
3
+ "version": "0.115.3-beta.6",
4
4
  "description": "React Native Component Kits",
5
5
  "main": "index.ts",
6
6
  "scripts": {},
@@ -1,45 +0,0 @@
1
- import React, {useContext} from 'react';
2
- import {View, ViewStyle} from 'react-native';
3
- import {ApplicationContext} from '../Application';
4
- import {Spacing} from '../Consts';
5
- import Svg, {Line} from 'react-native-svg';
6
-
7
- export interface DashDividerProps {
8
- /**
9
- * Custom styles for dash divider
10
- */
11
- style?: ViewStyle;
12
- }
13
-
14
- const DashDivider: React.FC<DashDividerProps> = ({style}) => {
15
- const {theme} = useContext(ApplicationContext);
16
- const borderColor = theme.colors.border.default;
17
-
18
- return (
19
- <View
20
- style={[
21
- {
22
- width: '100%',
23
- height: 1,
24
- marginVertical: Spacing.XS,
25
- },
26
- style,
27
- ]}>
28
- <Svg height="1" width="100%">
29
- <Line
30
- x1="0"
31
- y1="0"
32
- x2="100%"
33
- y2="0"
34
- stroke={borderColor}
35
- strokeWidth="1"
36
- strokeDasharray={`4, 4`}
37
- strokeLinecap={'round'}
38
- strokeLinejoin={'miter'}
39
- />
40
- </Svg>
41
- </View>
42
- );
43
- };
44
-
45
- export {DashDivider};