@momo-kits/foundation 0.80.9 → 0.81.2
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/Application/Components.tsx +47 -6
- package/Application/ModalScreen.tsx +24 -7
- package/Application/Navigation.ts +3 -5
- package/Application/NavigationContainer.tsx +2 -2
- package/Application/index.ts +12 -5
- package/Application/types.ts +14 -6
- package/Application/utils.tsx +15 -47
- package/Consts/colors+spacing+radius.ts +4 -0
- package/Image/index.tsx +21 -11
- package/Input/Input.tsx +5 -3
- package/Input/InputDropDown.tsx +6 -3
- package/Input/InputMoney.tsx +6 -3
- package/Input/InputOTP.tsx +7 -9
- package/Input/InputSearch.tsx +6 -9
- package/Input/InputTextArea.tsx +5 -3
- package/Input/common.tsx +2 -2
- package/Input/index.tsx +3 -1
- package/Layout/Card.tsx +18 -4
- package/Layout/ItemList.tsx +63 -0
- package/Layout/Screen.tsx +223 -176
- package/Layout/Section.tsx +2 -1
- package/Layout/index.ts +10 -1
- package/Layout/styles.ts +12 -0
- package/Layout/types.ts +2 -0
- package/Layout/utils.ts +2 -7
- package/Pagination/PaginationDot.tsx +6 -1
- package/Pagination/PaginationNumber.tsx +7 -4
- package/Pagination/PaginationWhiteDot.tsx +6 -1
- package/Pagination/styles.ts +3 -0
- package/Pagination/types.ts +2 -0
- package/Radio/types.ts +2 -2
- package/package.json +1 -1
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import React, {Fragment, useContext, useEffect, useState} from 'react';
|
|
2
2
|
import {
|
|
3
|
-
Alert,
|
|
4
3
|
Animated,
|
|
5
4
|
DeviceEventEmitter,
|
|
6
5
|
Platform,
|
|
7
6
|
StatusBar,
|
|
8
7
|
StyleSheet,
|
|
9
|
-
TouchableOpacity
|
|
8
|
+
TouchableOpacity,
|
|
10
9
|
View,
|
|
11
10
|
} from 'react-native';
|
|
12
11
|
import {TouchableOpacity as TouchableGesture} from 'react-native-gesture-handler';
|
|
@@ -14,6 +13,7 @@ import {ApplicationContext} from './index';
|
|
|
14
13
|
import {Colors, Radius, Spacing, Styles} from '../Consts';
|
|
15
14
|
import {Image} from '../Image';
|
|
16
15
|
import {
|
|
16
|
+
HeaderAnimatedProps,
|
|
17
17
|
HeaderBackgroundProps,
|
|
18
18
|
HeaderBackProps,
|
|
19
19
|
HeaderToolkitProps,
|
|
@@ -24,7 +24,8 @@ import {scaleSize, Text} from '../Text';
|
|
|
24
24
|
import {Icon} from '../Icon';
|
|
25
25
|
import {PopupNotify} from '../Popup';
|
|
26
26
|
|
|
27
|
-
const Touchable =
|
|
27
|
+
const Touchable =
|
|
28
|
+
Platform.OS === 'android' ? TouchableGesture : TouchableOpacity;
|
|
28
29
|
|
|
29
30
|
const styles = StyleSheet.create({
|
|
30
31
|
navigationButton: {
|
|
@@ -208,7 +209,7 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
|
208
209
|
headerImage = undefined;
|
|
209
210
|
}
|
|
210
211
|
const opacity = animatedValue?.interpolate({
|
|
211
|
-
inputRange: [0,
|
|
212
|
+
inputRange: [0, 114],
|
|
212
213
|
outputRange: [0, 1],
|
|
213
214
|
extrapolate: 'clamp',
|
|
214
215
|
});
|
|
@@ -274,8 +275,7 @@ const HeaderRightAction: React.FC<any> = ({children, ...restProps}) => {
|
|
|
274
275
|
const validateType = (child: React.ReactElement) => {
|
|
275
276
|
const valid = child?.type === NavigationButton || child?.type == Fragment;
|
|
276
277
|
if (__DEV__ && !valid) {
|
|
277
|
-
|
|
278
|
-
'Rule',
|
|
278
|
+
console.warn(
|
|
279
279
|
'HeaderRightAction contains element type of NavigationButton, Please check again.',
|
|
280
280
|
);
|
|
281
281
|
}
|
|
@@ -416,6 +416,46 @@ const HeaderToolkitAction: React.FC<any> = ({tintColor}) => {
|
|
|
416
416
|
return <View />;
|
|
417
417
|
};
|
|
418
418
|
|
|
419
|
+
const HeaderAnimated: React.FC<HeaderAnimatedProps> = ({
|
|
420
|
+
animatedValue,
|
|
421
|
+
image,
|
|
422
|
+
onPress,
|
|
423
|
+
}) => {
|
|
424
|
+
const scale = animatedValue.interpolate({
|
|
425
|
+
inputRange: [-300, 0, 300],
|
|
426
|
+
outputRange: [4, 1, 1],
|
|
427
|
+
extrapolate: 'clamp',
|
|
428
|
+
});
|
|
429
|
+
const opacity = animatedValue.interpolate({
|
|
430
|
+
inputRange: [0, 150, 300],
|
|
431
|
+
outputRange: [1, 0.5, 0],
|
|
432
|
+
extrapolate: 'clamp',
|
|
433
|
+
});
|
|
434
|
+
const translateY = animatedValue.interpolate({
|
|
435
|
+
inputRange: [-300, 0],
|
|
436
|
+
outputRange: [-80, -2],
|
|
437
|
+
extrapolate: 'clamp',
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
return (
|
|
441
|
+
<TouchableOpacity onPress={onPress}>
|
|
442
|
+
<Animated.View
|
|
443
|
+
style={{
|
|
444
|
+
height: 210,
|
|
445
|
+
opacity: opacity,
|
|
446
|
+
transform: [{scale}, {translateY}],
|
|
447
|
+
}}>
|
|
448
|
+
<Image
|
|
449
|
+
source={{
|
|
450
|
+
uri: image,
|
|
451
|
+
}}
|
|
452
|
+
style={{width: '100%', height: '100%'}}
|
|
453
|
+
/>
|
|
454
|
+
</Animated.View>
|
|
455
|
+
</TouchableOpacity>
|
|
456
|
+
);
|
|
457
|
+
};
|
|
458
|
+
|
|
419
459
|
export {
|
|
420
460
|
NavigationButton,
|
|
421
461
|
HeaderTitle,
|
|
@@ -424,4 +464,5 @@ export {
|
|
|
424
464
|
HeaderRightAction,
|
|
425
465
|
HeaderToolkitAction,
|
|
426
466
|
HeaderCustom,
|
|
467
|
+
HeaderAnimated,
|
|
427
468
|
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import React, {useContext, useEffect, useMemo, useRef} from 'react';
|
|
1
|
+
import React, {useContext, useEffect, useMemo, useRef, useState} from 'react';
|
|
2
2
|
import {
|
|
3
|
+
Dimensions,
|
|
4
|
+
Keyboard,
|
|
3
5
|
KeyboardAvoidingView,
|
|
4
6
|
Platform,
|
|
5
7
|
Pressable,
|
|
6
8
|
StyleSheet,
|
|
7
9
|
View,
|
|
8
|
-
Keyboard,
|
|
9
10
|
} from 'react-native';
|
|
10
11
|
import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
11
12
|
import {
|
|
@@ -90,6 +91,7 @@ const Modal: React.FC<ModalParams> = props => {
|
|
|
90
91
|
const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
91
92
|
const insets = useSafeAreaInsets();
|
|
92
93
|
const {theme, navigator} = useContext(ApplicationContext);
|
|
94
|
+
const [keyboardSnap, setKeyboardSnap] = useState(0);
|
|
93
95
|
const {screen, options, snapPoint}: BottomSheetParams = props.route.params;
|
|
94
96
|
const Component = useRef(screen).current;
|
|
95
97
|
const navigation = new Navigation(props.navigation, theme);
|
|
@@ -102,28 +104,41 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
102
104
|
|
|
103
105
|
const snapPoints = useMemo(() => {
|
|
104
106
|
if (snapPoint) {
|
|
105
|
-
|
|
107
|
+
const current = parseInt(snapPoint) + keyboardSnap * 100;
|
|
108
|
+
return [`${current}%`];
|
|
106
109
|
}
|
|
107
110
|
return ['50%', '70%', '90%'];
|
|
108
|
-
}, []);
|
|
111
|
+
}, [keyboardSnap]);
|
|
109
112
|
|
|
110
113
|
const bottomSheetRef = useRef<any>(null);
|
|
111
114
|
const mountedRef = useRef(true);
|
|
112
115
|
|
|
113
116
|
let backgroundColor = theme.colors.background.default;
|
|
117
|
+
let bottomInset = keyboardSnap * Dimensions.get('window').height;
|
|
118
|
+
if (bottomInset > 16) {
|
|
119
|
+
bottomInset -= 16;
|
|
120
|
+
}
|
|
114
121
|
if (options?.surface) {
|
|
115
122
|
backgroundColor = theme.colors.background.surface;
|
|
116
123
|
}
|
|
117
124
|
|
|
118
125
|
useEffect(() => {
|
|
119
|
-
const keyboardDidShow = Keyboard.addListener('keyboardDidShow',
|
|
120
|
-
|
|
121
|
-
|
|
126
|
+
const keyboardDidShow = Keyboard.addListener('keyboardDidShow', e => {
|
|
127
|
+
setKeyboardSnap(
|
|
128
|
+
e.endCoordinates.height / Dimensions.get('window').height,
|
|
129
|
+
);
|
|
130
|
+
bottomSheetRef.current?.expand();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const keyboardDidHide = Keyboard.addListener('keyboardDidHide', () => {
|
|
134
|
+
setKeyboardSnap(0);
|
|
135
|
+
});
|
|
122
136
|
|
|
123
137
|
bottomSheetRef.current?.present();
|
|
124
138
|
return () => {
|
|
125
139
|
mountedRef.current = false;
|
|
126
140
|
keyboardDidShow.remove();
|
|
141
|
+
keyboardDidHide.remove();
|
|
127
142
|
};
|
|
128
143
|
}, []);
|
|
129
144
|
|
|
@@ -145,6 +160,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
145
160
|
navigator?.pop();
|
|
146
161
|
}
|
|
147
162
|
}}
|
|
163
|
+
bottomInset={bottomInset}
|
|
148
164
|
handleComponent={null}
|
|
149
165
|
backdropComponent={backdropComponent}>
|
|
150
166
|
<BottomSheetView accessibilityLabel={'BottomSheet'}>
|
|
@@ -193,6 +209,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
193
209
|
/>
|
|
194
210
|
);
|
|
195
211
|
},
|
|
212
|
+
headerTintColor: theme.colors.text.default,
|
|
196
213
|
headerBackground: () => (
|
|
197
214
|
<HeaderBackground backgroundColor={backgroundColor} />
|
|
198
215
|
),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
import {NavigationProp} from '@react-navigation/native';
|
|
2
|
-
import {Alert} from 'react-native';
|
|
3
3
|
import {NavigationOptions, Theme} from './types';
|
|
4
4
|
import {HeaderRightAction} from './index';
|
|
5
5
|
import {getOptions} from './utils';
|
|
@@ -16,14 +16,12 @@ class Navigation {
|
|
|
16
16
|
|
|
17
17
|
private filterParams = (params: NavigationOptions) => {
|
|
18
18
|
if (params.headerRight) {
|
|
19
|
-
const headerRight = params.headerRight?.();
|
|
19
|
+
const headerRight = params.headerRight?.({}) as React.ReactElement;
|
|
20
20
|
const type = headerRight?.type;
|
|
21
21
|
if (type !== HeaderRightAction && type !== HeaderToolkitAction) {
|
|
22
|
-
|
|
23
|
-
'Rule',
|
|
22
|
+
console.warn(
|
|
24
23
|
'headerRight contains element type of HeaderRightAction | HeaderToolkitAction, Please check again.',
|
|
25
24
|
);
|
|
26
|
-
delete params.headerRight;
|
|
27
25
|
}
|
|
28
26
|
}
|
|
29
27
|
return params;
|
|
@@ -93,12 +93,12 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
93
93
|
name="Stack"
|
|
94
94
|
component={StackScreen}
|
|
95
95
|
initialParams={{screen}}
|
|
96
|
-
options={{...getStackOptions(
|
|
96
|
+
options={{...getStackOptions(), ...options}}
|
|
97
97
|
/>
|
|
98
98
|
<Stack.Screen
|
|
99
99
|
name="Dialog"
|
|
100
100
|
component={StackScreen}
|
|
101
|
-
options={getDialogOptions(
|
|
101
|
+
options={getDialogOptions()}
|
|
102
102
|
initialParams={{screen}}
|
|
103
103
|
/>
|
|
104
104
|
<Stack.Screen
|
package/Application/index.ts
CHANGED
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
import {NavigationContainer} from './NavigationContainer';
|
|
2
2
|
import Screen from '../Layout/Screen';
|
|
3
3
|
import {
|
|
4
|
-
HeaderRightAction,
|
|
5
4
|
NavigationButton,
|
|
6
|
-
HeaderToolkitAction,
|
|
7
5
|
HeaderTitle,
|
|
6
|
+
HeaderLeft,
|
|
7
|
+
HeaderBackground,
|
|
8
|
+
HeaderRightAction,
|
|
9
|
+
HeaderToolkitAction,
|
|
10
|
+
HeaderCustom,
|
|
11
|
+
HeaderAnimated,
|
|
8
12
|
} from './Components';
|
|
9
13
|
import BottomTab from './BottomTab';
|
|
10
14
|
import {createContext} from 'react';
|
|
11
15
|
import {defaultContext} from '../Consts';
|
|
12
16
|
|
|
13
17
|
const ApplicationContext = createContext(defaultContext);
|
|
14
|
-
|
|
15
18
|
export {
|
|
16
19
|
NavigationContainer,
|
|
17
20
|
ApplicationContext,
|
|
18
21
|
Screen,
|
|
22
|
+
BottomTab,
|
|
19
23
|
NavigationButton,
|
|
24
|
+
HeaderTitle,
|
|
25
|
+
HeaderLeft,
|
|
26
|
+
HeaderBackground,
|
|
20
27
|
HeaderRightAction,
|
|
21
28
|
HeaderToolkitAction,
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
HeaderCustom,
|
|
30
|
+
HeaderAnimated,
|
|
24
31
|
};
|
package/Application/types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {Animated} from 'react-native';
|
|
2
|
+
import {StackNavigationOptions} from '@react-navigation/stack';
|
|
2
3
|
import React from 'react';
|
|
3
4
|
import Navigator from './Navigator';
|
|
4
5
|
import {PopupNotifyProps} from '../Popup/types';
|
|
@@ -119,19 +120,15 @@ export type NavigationButtonProps = {
|
|
|
119
120
|
accessibilityLabel?: string;
|
|
120
121
|
};
|
|
121
122
|
|
|
122
|
-
export
|
|
123
|
+
export interface NavigationOptions extends StackNavigationOptions {
|
|
123
124
|
preventBack?: PopupNotifyProps;
|
|
124
125
|
onPressLeftHeader?: () => void;
|
|
125
126
|
surface?: boolean;
|
|
126
|
-
headerTransparent?: boolean;
|
|
127
127
|
hiddenBack?: boolean;
|
|
128
|
-
title?: string;
|
|
129
|
-
headerTitle?: (props?: any) => React.ReactElement;
|
|
130
128
|
headerTitleAlign?: 'left' | 'center';
|
|
131
129
|
customTitle?: TitleCustomProps;
|
|
132
|
-
headerRight?: (props?: any) => React.ReactElement;
|
|
133
130
|
animatedValue?: Animated.Value;
|
|
134
|
-
}
|
|
131
|
+
}
|
|
135
132
|
|
|
136
133
|
export interface HeaderBackProps extends NavigationButtonProps {
|
|
137
134
|
preventBack?: PopupNotifyProps;
|
|
@@ -164,6 +161,12 @@ export type HeaderToolkitProps = {
|
|
|
164
161
|
onAction?: (action: string) => void;
|
|
165
162
|
};
|
|
166
163
|
|
|
164
|
+
export type HeaderAnimatedProps = {
|
|
165
|
+
animatedValue: Animated.Value;
|
|
166
|
+
image: string;
|
|
167
|
+
onPress?: () => void;
|
|
168
|
+
};
|
|
169
|
+
|
|
167
170
|
export type BottomTabItemProps = {
|
|
168
171
|
name: string;
|
|
169
172
|
label: string;
|
|
@@ -182,3 +185,8 @@ export type BottomTabProps = {
|
|
|
182
185
|
focus?: any;
|
|
183
186
|
};
|
|
184
187
|
};
|
|
188
|
+
|
|
189
|
+
export type AnimatedHeader = {
|
|
190
|
+
type: 'default' | 'surface';
|
|
191
|
+
component?: (props?: any) => React.ReactElement;
|
|
192
|
+
};
|
package/Application/utils.tsx
CHANGED
|
@@ -13,35 +13,24 @@ import {
|
|
|
13
13
|
import {NavigationOptions, Theme} from './types';
|
|
14
14
|
import {Colors} from '../Consts';
|
|
15
15
|
|
|
16
|
-
const
|
|
17
|
-
if (theme.assets?.headerBackground) {
|
|
18
|
-
return {
|
|
19
|
-
headerTintColor: Colors.black_01,
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
return {
|
|
23
|
-
headerTintColor: theme.colors.text.default,
|
|
24
|
-
};
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const getStackOptions = (theme: Theme): StackNavigationOptions => {
|
|
16
|
+
const getStackOptions = (): StackNavigationOptions => {
|
|
28
17
|
return {
|
|
29
18
|
headerTitleAlign: 'left',
|
|
30
19
|
headerTitle: HeaderTitle,
|
|
31
|
-
headerBackground: HeaderBackground
|
|
20
|
+
headerBackground: (props: any) => <HeaderBackground {...props} />,
|
|
32
21
|
headerLeft: (props: any) => <HeaderLeft {...props} />,
|
|
33
22
|
headerRight: (props: any) => <HeaderToolkitAction {...props} />,
|
|
34
|
-
|
|
23
|
+
headerTintColor: Colors.black_01,
|
|
35
24
|
};
|
|
36
25
|
};
|
|
37
26
|
|
|
38
|
-
const getDialogOptions = (
|
|
27
|
+
const getDialogOptions = (): StackNavigationOptions => {
|
|
39
28
|
return {
|
|
40
29
|
headerTitleAlign: 'left',
|
|
41
30
|
headerTitle: HeaderTitle,
|
|
42
31
|
headerLeft: (props: any) => <HeaderLeft {...props} />,
|
|
43
|
-
headerBackground: HeaderBackground
|
|
44
|
-
|
|
32
|
+
headerBackground: (props: any) => <HeaderBackground {...props} />,
|
|
33
|
+
headerTintColor: Colors.black_01,
|
|
45
34
|
...TransitionPresets.ModalTransition,
|
|
46
35
|
};
|
|
47
36
|
};
|
|
@@ -72,8 +61,6 @@ const getModalOptions = (): StackNavigationOptions => {
|
|
|
72
61
|
};
|
|
73
62
|
|
|
74
63
|
const getOptions = (params: NavigationOptions, theme: Theme) => {
|
|
75
|
-
let backgroundProps: any;
|
|
76
|
-
let titleProps: any;
|
|
77
64
|
let options = {};
|
|
78
65
|
|
|
79
66
|
if (
|
|
@@ -99,36 +86,24 @@ const getOptions = (params: NavigationOptions, theme: Theme) => {
|
|
|
99
86
|
if (params.surface) {
|
|
100
87
|
options = {
|
|
101
88
|
...options,
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
useBorder: true,
|
|
89
|
+
headerTintColor: theme.colors.text.default,
|
|
90
|
+
headerBackground: () => (
|
|
91
|
+
<HeaderBackground
|
|
92
|
+
image={null}
|
|
93
|
+
backgroundColor={theme.colors.background.surface}
|
|
94
|
+
useBorder={true}
|
|
95
|
+
/>
|
|
96
|
+
),
|
|
111
97
|
};
|
|
112
98
|
} else {
|
|
113
99
|
options = {
|
|
114
100
|
...options,
|
|
115
|
-
|
|
101
|
+
headerTintColor: Colors.black_01,
|
|
116
102
|
headerBackground: HeaderBackground,
|
|
117
103
|
};
|
|
118
104
|
}
|
|
119
105
|
}
|
|
120
106
|
|
|
121
|
-
if (params.animatedValue) {
|
|
122
|
-
backgroundProps = {...backgroundProps, animatedValue: params.animatedValue};
|
|
123
|
-
titleProps = {animatedValue: params.animatedValue};
|
|
124
|
-
options = {
|
|
125
|
-
...options,
|
|
126
|
-
headerTitle: (props: any) => {
|
|
127
|
-
return <HeaderTitle {...titleProps} {...props} />;
|
|
128
|
-
},
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
107
|
if (params.customTitle) {
|
|
133
108
|
options = {
|
|
134
109
|
...options,
|
|
@@ -139,13 +114,6 @@ const getOptions = (params: NavigationOptions, theme: Theme) => {
|
|
|
139
114
|
};
|
|
140
115
|
}
|
|
141
116
|
|
|
142
|
-
if (backgroundProps) {
|
|
143
|
-
options = {
|
|
144
|
-
...options,
|
|
145
|
-
headerBackground: () => <HeaderBackground {...backgroundProps} />,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
117
|
return {
|
|
150
118
|
...params,
|
|
151
119
|
...options,
|
package/Image/index.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {useContext, useState} from 'react';
|
|
1
|
+
import React, {useContext, useRef, useState} from 'react';
|
|
2
2
|
import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native';
|
|
3
3
|
import FastImage from 'react-native-fast-image';
|
|
4
4
|
import styles from './styles';
|
|
@@ -14,6 +14,8 @@ export interface ImageProps extends FastImagePropsWithoutStyle {
|
|
|
14
14
|
accessibilityLabel?: string;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
type Status = 'success' | 'loading' | 'error';
|
|
18
|
+
|
|
17
19
|
const Image: React.FC<ImageProps> = ({
|
|
18
20
|
style,
|
|
19
21
|
source,
|
|
@@ -21,19 +23,20 @@ const Image: React.FC<ImageProps> = ({
|
|
|
21
23
|
...rest
|
|
22
24
|
}) => {
|
|
23
25
|
const {theme} = useContext(ApplicationContext);
|
|
24
|
-
const
|
|
25
|
-
const [
|
|
26
|
+
const error = useRef(false);
|
|
27
|
+
const [status, setStatus] = useState<Status>(
|
|
28
|
+
rest.loading ? 'loading' : 'success',
|
|
29
|
+
);
|
|
26
30
|
|
|
27
31
|
/**
|
|
28
32
|
* render content loading | fail | rendered
|
|
29
|
-
* @returns {JSX.Element}
|
|
30
33
|
*/
|
|
31
34
|
const renderContent = () => {
|
|
32
|
-
if (loading ||
|
|
35
|
+
if (status == 'loading' || status == 'error') {
|
|
33
36
|
let content = (
|
|
34
37
|
<Skeleton style={[StyleSheet.absoluteFill, styles.image]} />
|
|
35
38
|
);
|
|
36
|
-
if (
|
|
39
|
+
if (status == 'error') {
|
|
37
40
|
content = (
|
|
38
41
|
<View style={Styles.flexCenter}>
|
|
39
42
|
<Icon source="media_fail" color={theme.colors.text.disable} />
|
|
@@ -63,12 +66,19 @@ const Image: React.FC<ImageProps> = ({
|
|
|
63
66
|
{...rest}
|
|
64
67
|
source={source}
|
|
65
68
|
style={styles.image}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
onLoadStart={() => {
|
|
70
|
+
error.current = false;
|
|
71
|
+
}}
|
|
72
|
+
onLoadEnd={() => {
|
|
73
|
+
if (error.current) {
|
|
74
|
+
setStatus('error');
|
|
75
|
+
} else {
|
|
76
|
+
setStatus('success');
|
|
77
|
+
}
|
|
78
|
+
}}
|
|
79
|
+
onError={() => {
|
|
80
|
+
error.current = true;
|
|
69
81
|
}}
|
|
70
|
-
onLoadEnd={() => setLoading(false)}
|
|
71
|
-
onError={() => setFail(true)}
|
|
72
82
|
/>
|
|
73
83
|
{renderContent()}
|
|
74
84
|
</View>
|
package/Input/Input.tsx
CHANGED
|
@@ -35,6 +35,7 @@ const Input = forwardRef(
|
|
|
35
35
|
loading,
|
|
36
36
|
leadingIcon,
|
|
37
37
|
leadingIconColor,
|
|
38
|
+
style,
|
|
38
39
|
...props
|
|
39
40
|
}: InputProps,
|
|
40
41
|
ref,
|
|
@@ -43,6 +44,7 @@ const Input = forwardRef(
|
|
|
43
44
|
const [focused, setFocused] = useState(false);
|
|
44
45
|
const [haveValue, setHaveValue] = useState(!!value || !!props.defaultValue);
|
|
45
46
|
const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
|
|
47
|
+
const accessibilityLabel = `Input/${floatingValue ?? placeholder}`;
|
|
46
48
|
|
|
47
49
|
const onClearText = () => {
|
|
48
50
|
inputRef?.current?.clear();
|
|
@@ -112,7 +114,7 @@ const Input = forwardRef(
|
|
|
112
114
|
)}
|
|
113
115
|
<TextInput
|
|
114
116
|
{...props}
|
|
115
|
-
accessibilityLabel={
|
|
117
|
+
accessibilityLabel={accessibilityLabel}
|
|
116
118
|
editable={!disabled}
|
|
117
119
|
textAlignVertical="center"
|
|
118
120
|
ref={inputRef}
|
|
@@ -153,8 +155,8 @@ const Input = forwardRef(
|
|
|
153
155
|
|
|
154
156
|
return (
|
|
155
157
|
<View
|
|
156
|
-
style={styles.wrapper}
|
|
157
|
-
accessibilityLabel={
|
|
158
|
+
style={[style, styles.wrapper]}
|
|
159
|
+
accessibilityLabel={accessibilityLabel}>
|
|
158
160
|
{renderInputView()}
|
|
159
161
|
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
160
162
|
</View>
|
package/Input/InputDropDown.tsx
CHANGED
|
@@ -25,10 +25,13 @@ const InputDropDown = ({
|
|
|
25
25
|
loading,
|
|
26
26
|
leadingIcon,
|
|
27
27
|
leadingIconColor,
|
|
28
|
+
style,
|
|
28
29
|
...props
|
|
29
30
|
}: InputDropDownProps) => {
|
|
30
31
|
const {theme} = useContext(ApplicationContext);
|
|
31
32
|
const full = !!value || !!placeholder;
|
|
33
|
+
const accessibilityLabel = `InputDropDown/${floatingValue ?? placeholder}`;
|
|
34
|
+
|
|
32
35
|
const renderIcon = (color: string | undefined) => {
|
|
33
36
|
if (loading) {
|
|
34
37
|
return <Loader type={'spinner'} color={color} />;
|
|
@@ -79,7 +82,7 @@ const InputDropDown = ({
|
|
|
79
82
|
<TextInput
|
|
80
83
|
{...props}
|
|
81
84
|
onPressIn={onPress}
|
|
82
|
-
accessibilityLabel={
|
|
85
|
+
accessibilityLabel={accessibilityLabel}
|
|
83
86
|
editable={false}
|
|
84
87
|
textAlignVertical="top"
|
|
85
88
|
style={[
|
|
@@ -105,8 +108,8 @@ const InputDropDown = ({
|
|
|
105
108
|
return (
|
|
106
109
|
<TouchableOpacity
|
|
107
110
|
onPress={onPress}
|
|
108
|
-
style={full && styles.wrapper}
|
|
109
|
-
accessibilityLabel={
|
|
111
|
+
style={[style, full && styles.wrapper]}
|
|
112
|
+
accessibilityLabel={accessibilityLabel}>
|
|
110
113
|
{renderInputView()}
|
|
111
114
|
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
112
115
|
</TouchableOpacity>
|
package/Input/InputMoney.tsx
CHANGED
|
@@ -29,6 +29,7 @@ const InputMoney = forwardRef(
|
|
|
29
29
|
iconColor,
|
|
30
30
|
required,
|
|
31
31
|
errorSpacing,
|
|
32
|
+
style,
|
|
32
33
|
...props
|
|
33
34
|
}: InputMoneyProps,
|
|
34
35
|
ref,
|
|
@@ -37,6 +38,8 @@ const InputMoney = forwardRef(
|
|
|
37
38
|
const [focused, setFocused] = useState(false);
|
|
38
39
|
const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
|
|
39
40
|
const [value, setValue] = useState('');
|
|
41
|
+
const accessibilityLabel = `InputMoney/${floatingValue}`;
|
|
42
|
+
|
|
40
43
|
const onClearText = () => {
|
|
41
44
|
inputRef?.current?.clear();
|
|
42
45
|
setValue('');
|
|
@@ -91,7 +94,7 @@ const InputMoney = forwardRef(
|
|
|
91
94
|
<View style={styles.inputView}>
|
|
92
95
|
<TextInput
|
|
93
96
|
{...props}
|
|
94
|
-
accessibilityLabel={
|
|
97
|
+
accessibilityLabel={accessibilityLabel}
|
|
95
98
|
editable={!disabled}
|
|
96
99
|
textAlignVertical="top"
|
|
97
100
|
ref={inputRef}
|
|
@@ -131,8 +134,8 @@ const InputMoney = forwardRef(
|
|
|
131
134
|
|
|
132
135
|
return (
|
|
133
136
|
<View
|
|
134
|
-
style={styles.wrapper}
|
|
135
|
-
accessibilityLabel={
|
|
137
|
+
style={[style, styles.wrapper]}
|
|
138
|
+
accessibilityLabel={accessibilityLabel}>
|
|
136
139
|
{renderInputView()}
|
|
137
140
|
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
138
141
|
</View>
|
package/Input/InputOTP.tsx
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, {FC, useContext, useEffect, useRef, useState} from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Animated,
|
|
4
|
-
KeyboardType,
|
|
5
4
|
NativeSyntheticEvent,
|
|
6
5
|
TextInput,
|
|
7
6
|
TextInputFocusEventData,
|
|
@@ -69,6 +68,7 @@ const InputOTP: FC<InputOTPProps> = ({
|
|
|
69
68
|
onFocus,
|
|
70
69
|
onBlur,
|
|
71
70
|
dataType = 'number',
|
|
71
|
+
style,
|
|
72
72
|
...props
|
|
73
73
|
}) => {
|
|
74
74
|
const MAX_LENGTH = 10;
|
|
@@ -76,6 +76,7 @@ const InputOTP: FC<InputOTPProps> = ({
|
|
|
76
76
|
const [focused, setFocused] = useState(false);
|
|
77
77
|
const inputRef = useRef<TextInput>(null);
|
|
78
78
|
const {theme} = useContext(ApplicationContext);
|
|
79
|
+
const accessibilityLabel = `InputOTP/${floatingValue ?? placeholder}`;
|
|
79
80
|
|
|
80
81
|
const onFocusInput = () => {
|
|
81
82
|
setFocused(true);
|
|
@@ -157,9 +158,6 @@ const InputOTP: FC<InputOTPProps> = ({
|
|
|
157
158
|
};
|
|
158
159
|
|
|
159
160
|
const renderInputView = () => {
|
|
160
|
-
let placeholderColor = theme.colors.text.hint;
|
|
161
|
-
const keyboardType: KeyboardType =
|
|
162
|
-
dataType === 'number' ? 'number-pad' : 'default';
|
|
163
161
|
return (
|
|
164
162
|
<View
|
|
165
163
|
style={[
|
|
@@ -182,16 +180,16 @@ const InputOTP: FC<InputOTPProps> = ({
|
|
|
182
180
|
<View style={styles.inputView}>
|
|
183
181
|
<TextInput
|
|
184
182
|
{...props}
|
|
185
|
-
accessibilityLabel={
|
|
183
|
+
accessibilityLabel={accessibilityLabel}
|
|
186
184
|
ref={inputRef}
|
|
187
185
|
value={value}
|
|
188
186
|
onChangeText={_onChangeText}
|
|
189
|
-
keyboardType={
|
|
187
|
+
keyboardType={dataType === 'number' ? 'number-pad' : 'default'}
|
|
190
188
|
onFocus={onFocusInput}
|
|
191
189
|
onBlur={onBlurInput}
|
|
192
190
|
style={{opacity: 0}}
|
|
193
191
|
selectionColor={theme.colors.primary}
|
|
194
|
-
placeholderTextColor={
|
|
192
|
+
placeholderTextColor={theme.colors.text.hint}
|
|
195
193
|
/>
|
|
196
194
|
</View>
|
|
197
195
|
</View>
|
|
@@ -202,8 +200,8 @@ const InputOTP: FC<InputOTPProps> = ({
|
|
|
202
200
|
<TouchableOpacity
|
|
203
201
|
activeOpacity={1}
|
|
204
202
|
onPress={onFocusInput}
|
|
205
|
-
style={styles.otpWrapper}
|
|
206
|
-
accessibilityLabel={
|
|
203
|
+
style={[style, styles.otpWrapper]}
|
|
204
|
+
accessibilityLabel={accessibilityLabel}>
|
|
207
205
|
{renderInputView()}
|
|
208
206
|
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
209
207
|
</TouchableOpacity>
|