dhre-ui-kit 0.0.1
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/README.md +1 -0
- package/package.json +104 -0
- package/src/App.tsx +146 -0
- package/src/assets/images/calenderDots.svg +1 -0
- package/src/assets/index.ts +2 -0
- package/src/components/autoOtpReader/AutoOtpReader.test.tsx +56 -0
- package/src/components/autoOtpReader/AutoOtpReader.tsx +79 -0
- package/src/components/autoOtpReader/index.ts +1 -0
- package/src/components/badge/Badge.styles.ts +20 -0
- package/src/components/badge/Badge.test.tsx +45 -0
- package/src/components/badge/Badge.tsx +47 -0
- package/src/components/badge/index.ts +1 -0
- package/src/components/bottomDrawer/BottomDrawer.interface.ts +12 -0
- package/src/components/bottomDrawer/BottomDrawer.styles.ts +31 -0
- package/src/components/bottomDrawer/BottomDrawer.test.tsx +19 -0
- package/src/components/bottomDrawer/BottomDrawer.tsx +43 -0
- package/src/components/bottomDrawer/index.ts +1 -0
- package/src/components/button/Button.interface.ts +18 -0
- package/src/components/button/Button.styles.ts +78 -0
- package/src/components/button/Button.test.tsx +43 -0
- package/src/components/button/Button.tsx +53 -0
- package/src/components/button/index.ts +1 -0
- package/src/components/cards/Cards.interface.ts +13 -0
- package/src/components/cards/Cards.styles.ts +59 -0
- package/src/components/cards/Cards.test.tsx +41 -0
- package/src/components/cards/Cards.tsx +69 -0
- package/src/components/cards/index.ts +1 -0
- package/src/components/checkBox/CheckBox.interface.ts +10 -0
- package/src/components/checkBox/CheckBox.styles.ts +36 -0
- package/src/components/checkBox/CheckBox.test.tsx +46 -0
- package/src/components/checkBox/CheckBox.tsx +42 -0
- package/src/components/checkBox/index.ts +1 -0
- package/src/components/customDropdown/CustomDropdown.interface.ts +15 -0
- package/src/components/customDropdown/CustomDropdown.styles.tsx +46 -0
- package/src/components/customDropdown/CustomDropdown.test.tsx +30 -0
- package/src/components/customDropdown/CustomDropdown.tsx +106 -0
- package/src/components/customDropdown/index.ts +1 -0
- package/src/components/customInputText/CustomInputText.interface.ts +20 -0
- package/src/components/customInputText/CustomInputText.styles.ts +56 -0
- package/src/components/customInputText/CustomInputText.test.tsx +37 -0
- package/src/components/customInputText/CustomInputText.tsx +120 -0
- package/src/components/customInputText/index.ts +1 -0
- package/src/components/customText/CustomText.tsx +31 -0
- package/src/components/customText/index.ts +1 -0
- package/src/components/customTooltip/CustomTooltip.interface.ts +14 -0
- package/src/components/customTooltip/CustomTooltip.styles.ts +23 -0
- package/src/components/customTooltip/CustomTooltip.test.tsx +18 -0
- package/src/components/customTooltip/CustomTooltip.tsx +46 -0
- package/src/components/customTooltip/index.ts +1 -0
- package/src/components/customTypography/CustomTypography.tsx +25 -0
- package/src/components/fileUpload/FileUpload.styles.ts +41 -0
- package/src/components/fileUpload/FileUpload.test.tsx +39 -0
- package/src/components/fileUpload/FileUpload.tsx +65 -0
- package/src/components/fileUpload/index.ts +1 -0
- package/src/components/notification/Notification.interface.ts +61 -0
- package/src/components/notification/Notification.styles.ts +33 -0
- package/src/components/notification/Notification.test.tsx +116 -0
- package/src/components/notification/Notification.tsx +156 -0
- package/src/components/pdfView/PdfView.test.tsx +10 -0
- package/src/components/pdfView/PdfView.tsx +18 -0
- package/src/components/pdfView/index.ts +1 -0
- package/src/components/popup/PopUp.interface.ts +9 -0
- package/src/components/popup/PopUp.styles.ts +52 -0
- package/src/components/popup/PopUp.test.tsx +35 -0
- package/src/components/popup/PopUp.tsx +60 -0
- package/src/components/popup/index.ts +1 -0
- package/src/components/progressBar/ProgressBar.test.tsx +78 -0
- package/src/components/progressBar/ProgressBar.tsx +93 -0
- package/src/components/progressBar/index.ts +1 -0
- package/src/components/property360View/Property360View.test.tsx +24 -0
- package/src/components/property360View/Property360View.tsx +19 -0
- package/src/components/property360View/index.ts +1 -0
- package/src/components/rating/Rating.styles.ts +13 -0
- package/src/components/rating/Rating.test.tsx +61 -0
- package/src/components/rating/Rating.tsx +96 -0
- package/src/components/rating/index.ts +1 -0
- package/src/components/tabs/Tabs.interface.ts +13 -0
- package/src/components/tabs/Tabs.styles.ts +36 -0
- package/src/components/tabs/Tabs.test.tsx +20 -0
- package/src/components/tabs/Tabs.tsx +65 -0
- package/src/components/tabs/index.ts +1 -0
- package/src/components/tags/Tags.interface.ts +12 -0
- package/src/components/tags/Tags.styles.ts +36 -0
- package/src/components/tags/Tags.test.tsx +22 -0
- package/src/components/tags/Tags.tsx +76 -0
- package/src/components/tags/index.ts +1 -0
- package/src/components/toggleButton/ToggleButton.styles.ts +40 -0
- package/src/components/toggleButton/ToggleButton.test.tsx +33 -0
- package/src/components/toggleButton/ToggleButton.tsx +78 -0
- package/src/components/toggleButton/index.ts +1 -0
- package/src/index.ts +19 -0
- package/src/theme/ThemeContext.tsx +32 -0
- package/src/theme/colors.ts +156 -0
- package/src/theme/fonts.ts +303 -0
- package/src/theme/themes.ts +20 -0
- package/src/theme/withThemeProvider.tsx +14 -0
- package/src/utils/appEnum.ts +17 -0
- package/src/utils/commonStyles.ts +17 -0
- package/src/utils/constants.ts +17 -0
- package/src/utils/deviceUtils.ts +9 -0
- package/src/utils/regex.ts +1 -0
- package/src/utils/stylehelper.ts +13 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import {Pressable, View} from 'react-native';
|
|
2
|
+
import React, {useState} from 'react';
|
|
3
|
+
import {DHRE_COLORS_BG, DHRE_COLORS_TEXT} from '../../theme/colors';
|
|
4
|
+
import {CustomDropdownProps} from './CustomDropdown.interface';
|
|
5
|
+
import styles from './CustomDropdown.styles';
|
|
6
|
+
import {moderateScale} from '../../utils/stylehelper';
|
|
7
|
+
import CustomTypography from '../customTypography/CustomTypography';
|
|
8
|
+
|
|
9
|
+
const CustomDropdown: React.FC<CustomDropdownProps> = ({
|
|
10
|
+
label,
|
|
11
|
+
placeholder = 'Choose Option',
|
|
12
|
+
options,
|
|
13
|
+
selectedValue,
|
|
14
|
+
oneSelect,
|
|
15
|
+
testId = 'CUSTOM-DROPDOWN',
|
|
16
|
+
iconName,
|
|
17
|
+
iconStyle,
|
|
18
|
+
upArrowIcon,
|
|
19
|
+
downArrowIcon,
|
|
20
|
+
}) => {
|
|
21
|
+
const [showOptions, setShowOptions] = useState(false);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<View testID={testId}>
|
|
25
|
+
<CustomTypography
|
|
26
|
+
variant="P3regular"
|
|
27
|
+
style={styles.labelStyle}
|
|
28
|
+
text={label}
|
|
29
|
+
/>
|
|
30
|
+
<Pressable
|
|
31
|
+
testID={`${testId}-BTN`}
|
|
32
|
+
style={styles.dropDownStyle}
|
|
33
|
+
onPress={() => setShowOptions(!showOptions)}>
|
|
34
|
+
{iconName && (
|
|
35
|
+
<View style={iconStyle}>
|
|
36
|
+
{React.cloneElement(iconName, {
|
|
37
|
+
width: moderateScale(24),
|
|
38
|
+
height: moderateScale(24),
|
|
39
|
+
style: styles.iconStyle,
|
|
40
|
+
})}
|
|
41
|
+
</View>
|
|
42
|
+
)}
|
|
43
|
+
<CustomTypography
|
|
44
|
+
variant="P3regular"
|
|
45
|
+
style={styles.selectedValueStyle}
|
|
46
|
+
text={selectedValue ? selectedValue.label : placeholder}
|
|
47
|
+
/>
|
|
48
|
+
<View>
|
|
49
|
+
{showOptions
|
|
50
|
+
? React.cloneElement(upArrowIcon, {
|
|
51
|
+
width: moderateScale(24),
|
|
52
|
+
height: moderateScale(24),
|
|
53
|
+
})
|
|
54
|
+
: React.cloneElement(downArrowIcon, {
|
|
55
|
+
width: moderateScale(24),
|
|
56
|
+
height: moderateScale(24),
|
|
57
|
+
})}
|
|
58
|
+
</View>
|
|
59
|
+
</Pressable>
|
|
60
|
+
{showOptions && (
|
|
61
|
+
<View style={styles.optionContainer}>
|
|
62
|
+
{options?.map(({id, value, label}) => (
|
|
63
|
+
<Pressable
|
|
64
|
+
key={id}
|
|
65
|
+
testID={`${testId}-${label}-BTN`}
|
|
66
|
+
onPress={() => {
|
|
67
|
+
setShowOptions(!showOptions);
|
|
68
|
+
oneSelect({id, value, label});
|
|
69
|
+
}}
|
|
70
|
+
style={[
|
|
71
|
+
styles.item,
|
|
72
|
+
{
|
|
73
|
+
backgroundColor:
|
|
74
|
+
id === selectedValue?.id
|
|
75
|
+
? DHRE_COLORS_BG.DH_GREY1
|
|
76
|
+
: DHRE_COLORS_TEXT.DH_WHITE,
|
|
77
|
+
},
|
|
78
|
+
]}>
|
|
79
|
+
{iconName && (
|
|
80
|
+
<View style={iconStyle}>
|
|
81
|
+
{React.cloneElement(iconName, {
|
|
82
|
+
width: moderateScale(24),
|
|
83
|
+
height: moderateScale(24),
|
|
84
|
+
style: styles.iconStyle,
|
|
85
|
+
})}
|
|
86
|
+
</View>
|
|
87
|
+
)}
|
|
88
|
+
<CustomTypography
|
|
89
|
+
variant="P3regular"
|
|
90
|
+
style={{
|
|
91
|
+
color:
|
|
92
|
+
id === selectedValue?.id
|
|
93
|
+
? DHRE_COLORS_TEXT.DH_BLACK
|
|
94
|
+
: DHRE_COLORS_TEXT.DH_TEXTDARK,
|
|
95
|
+
}}
|
|
96
|
+
text={label}
|
|
97
|
+
/>
|
|
98
|
+
</Pressable>
|
|
99
|
+
))}
|
|
100
|
+
</View>
|
|
101
|
+
)}
|
|
102
|
+
</View>
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export default CustomDropdown;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {default} from './CustomDropdown';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {ReactElement} from 'react';
|
|
2
|
+
import {TextInputProps} from 'react-native';
|
|
3
|
+
|
|
4
|
+
export interface CustomTextInputProps extends TextInputProps {
|
|
5
|
+
label: string;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
errorMessage?: string;
|
|
9
|
+
successMessage?: string;
|
|
10
|
+
testID?: string;
|
|
11
|
+
handleFocus?: () => void;
|
|
12
|
+
handleBlur?: () => void;
|
|
13
|
+
handleOnChangeText?: (text: string) => void;
|
|
14
|
+
secureTextEntry?: boolean;
|
|
15
|
+
isSearchBar?: boolean;
|
|
16
|
+
multiline?: boolean;
|
|
17
|
+
rightIcon1?: ReactElement;
|
|
18
|
+
rightIcon2?: ReactElement;
|
|
19
|
+
searchIcon?: ReactElement;
|
|
20
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {StyleSheet} from 'react-native';
|
|
2
|
+
import {
|
|
3
|
+
DHRE_COLORS_TEXT,
|
|
4
|
+
DHRE_COLORS_BG,
|
|
5
|
+
DHRE_COLORS_ALERT,
|
|
6
|
+
} from '../../theme/colors';
|
|
7
|
+
import {FONT_STYLES} from '../../theme/fonts';
|
|
8
|
+
import {
|
|
9
|
+
horizontalScale,
|
|
10
|
+
moderateScale,
|
|
11
|
+
verticalScale,
|
|
12
|
+
} from '../../utils/stylehelper';
|
|
13
|
+
|
|
14
|
+
const styles = StyleSheet.create({
|
|
15
|
+
labelStyle: {
|
|
16
|
+
color: DHRE_COLORS_TEXT.DH_TEXTDARK,
|
|
17
|
+
},
|
|
18
|
+
inputContainer: {
|
|
19
|
+
flexDirection: 'row',
|
|
20
|
+
justifyContent: 'space-between',
|
|
21
|
+
marginVertical: verticalScale(8),
|
|
22
|
+
paddingHorizontal: horizontalScale(20),
|
|
23
|
+
paddingVertical: verticalScale(12),
|
|
24
|
+
backgroundColor: DHRE_COLORS_TEXT.DH_WHITE,
|
|
25
|
+
borderWidth: 1,
|
|
26
|
+
borderColor: DHRE_COLORS_BG.DH_LINE_GREY_700,
|
|
27
|
+
borderRadius: moderateScale(24),
|
|
28
|
+
},
|
|
29
|
+
input: {
|
|
30
|
+
flex: 1,
|
|
31
|
+
...FONT_STYLES.P2medium,
|
|
32
|
+
color: DHRE_COLORS_TEXT.DH_BLACK,
|
|
33
|
+
},
|
|
34
|
+
inputFocused: {
|
|
35
|
+
borderColor: DHRE_COLORS_TEXT.DH_BLACK,
|
|
36
|
+
},
|
|
37
|
+
inputError: {
|
|
38
|
+
borderColor: DHRE_COLORS_ALERT.DH_ALERT_ORANGE,
|
|
39
|
+
},
|
|
40
|
+
inputSucess: {
|
|
41
|
+
borderColor: DHRE_COLORS_ALERT.DH_SUCCESS_GREEN,
|
|
42
|
+
},
|
|
43
|
+
disableInputStyle: {
|
|
44
|
+
borderColor: DHRE_COLORS_BG.DH_GREY1,
|
|
45
|
+
backgroundColor: DHRE_COLORS_BG.DH_GREY1,
|
|
46
|
+
//need to check background and border color
|
|
47
|
+
},
|
|
48
|
+
disableTextStyle: {
|
|
49
|
+
color: DHRE_COLORS_TEXT.DH_TEXTLIGHTEST,
|
|
50
|
+
},
|
|
51
|
+
crossIconStyle: {marginLeft: horizontalScale(12)},
|
|
52
|
+
eyeIconStyle: {marginLeft: horizontalScale(16)},
|
|
53
|
+
searchIconStyle: {marginRight: horizontalScale(12)},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export default styles;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {it} from '@jest/globals';
|
|
3
|
+
import {fireEvent, render} from '@testing-library/react-native';
|
|
4
|
+
import CustomTextInput from './CustomInputText';
|
|
5
|
+
|
|
6
|
+
const mockProps = {
|
|
7
|
+
testID: 'CUSTOM-TEST-INPUT',
|
|
8
|
+
label: 'Email',
|
|
9
|
+
placeholder: 'Email',
|
|
10
|
+
disabled: false,
|
|
11
|
+
errorMessage: '',
|
|
12
|
+
successMessage: '',
|
|
13
|
+
handelFocus: jest.fn(),
|
|
14
|
+
handelBlur: jest.fn(),
|
|
15
|
+
handelOnChangeText: jest.fn(),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
describe('Custom Text Input Component', () => {
|
|
19
|
+
it('Component renders correctly', () => {
|
|
20
|
+
const {getByTestId} = render(<CustomTextInput {...mockProps} />);
|
|
21
|
+
expect(getByTestId('CUSTOM-TEST-INPUT')).toBeTruthy();
|
|
22
|
+
const textInput = getByTestId('CUSTOM-TEST-INPUT');
|
|
23
|
+
fireEvent.changeText(textInput, 'test@example.com');
|
|
24
|
+
expect(mockProps.handelOnChangeText).not.toHaveBeenCalledWith(
|
|
25
|
+
'test@example.com',
|
|
26
|
+
);
|
|
27
|
+
fireEvent(textInput, 'focus');
|
|
28
|
+
fireEvent(textInput, 'blur');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('Check blur method when value is empty', () => {
|
|
32
|
+
const {getByTestId} = render(<CustomTextInput {...mockProps} />);
|
|
33
|
+
expect(getByTestId('CUSTOM-TEST-INPUT')).toBeTruthy();
|
|
34
|
+
const textInput = getByTestId('CUSTOM-TEST-INPUT');
|
|
35
|
+
fireEvent(textInput, 'blur');
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import React, {useState} from 'react';
|
|
2
|
+
import {TextInput, View} from 'react-native';
|
|
3
|
+
import {DHRE_COLORS_ALERT, DHRE_COLORS_TEXT} from '../../theme/colors';
|
|
4
|
+
import {moderateScale} from '../../utils/stylehelper';
|
|
5
|
+
import {CustomTextInputProps} from './CustomInputText.interface';
|
|
6
|
+
import styles from './CustomInputText.styles';
|
|
7
|
+
import CustomTypography from '../customTypography/CustomTypography';
|
|
8
|
+
|
|
9
|
+
const CustomTextInput: React.FC<CustomTextInputProps> = ({
|
|
10
|
+
label,
|
|
11
|
+
placeholder,
|
|
12
|
+
disabled = false,
|
|
13
|
+
errorMessage,
|
|
14
|
+
successMessage,
|
|
15
|
+
testID = 'CUSTOM-TEST-INPUT',
|
|
16
|
+
handleFocus,
|
|
17
|
+
handleBlur,
|
|
18
|
+
handleOnChangeText,
|
|
19
|
+
secureTextEntry = false,
|
|
20
|
+
isSearchBar = false,
|
|
21
|
+
multiline,
|
|
22
|
+
rightIcon1,
|
|
23
|
+
rightIcon2,
|
|
24
|
+
searchIcon,
|
|
25
|
+
...props
|
|
26
|
+
}) => {
|
|
27
|
+
const [value, setValue] = useState('');
|
|
28
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
29
|
+
const [error, setError] = useState(!!errorMessage);
|
|
30
|
+
const [isSecureTextEntry, setIsSecureTextEntry] = useState(secureTextEntry);
|
|
31
|
+
|
|
32
|
+
const onFocus = () => {
|
|
33
|
+
handleFocus?.();
|
|
34
|
+
setIsFocused(true);
|
|
35
|
+
setError(false);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const onBlur = () => {
|
|
39
|
+
handleBlur?.();
|
|
40
|
+
if (!value) {
|
|
41
|
+
setError(true);
|
|
42
|
+
}
|
|
43
|
+
setIsFocused(false);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const handleIconPress1 = () => setValue('');
|
|
47
|
+
const handleIconPress2 = () => setIsSecureTextEntry(!isSecureTextEntry);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<View testID={testID}>
|
|
51
|
+
<CustomTypography
|
|
52
|
+
variant="P3medium"
|
|
53
|
+
style={[styles.labelStyle, disabled && styles.disableTextStyle]}
|
|
54
|
+
text={label}
|
|
55
|
+
/>
|
|
56
|
+
<View
|
|
57
|
+
style={[
|
|
58
|
+
styles.inputContainer,
|
|
59
|
+
isFocused && styles.inputFocused,
|
|
60
|
+
error && styles.inputError,
|
|
61
|
+
disabled && styles.disableInputStyle,
|
|
62
|
+
successMessage ? styles.inputSucess : {},
|
|
63
|
+
{
|
|
64
|
+
height: multiline ? 120 : 48,
|
|
65
|
+
alignItems: multiline ? 'flex-start' : 'center',
|
|
66
|
+
},
|
|
67
|
+
]}>
|
|
68
|
+
{isSearchBar &&
|
|
69
|
+
searchIcon &&
|
|
70
|
+
React.cloneElement(searchIcon, {
|
|
71
|
+
width: moderateScale(24),
|
|
72
|
+
height: moderateScale(24),
|
|
73
|
+
style: styles.searchIconStyle,
|
|
74
|
+
})}
|
|
75
|
+
<TextInput
|
|
76
|
+
{...props}
|
|
77
|
+
onFocus={onFocus}
|
|
78
|
+
onBlur={onBlur}
|
|
79
|
+
style={styles.input}
|
|
80
|
+
placeholderTextColor={DHRE_COLORS_TEXT.DH_TEXTLIGHTEST}
|
|
81
|
+
editable={!disabled}
|
|
82
|
+
value={value}
|
|
83
|
+
onChangeText={val => {
|
|
84
|
+
setValue(val);
|
|
85
|
+
handleOnChangeText?.(val);
|
|
86
|
+
}}
|
|
87
|
+
secureTextEntry={isSecureTextEntry}
|
|
88
|
+
/>
|
|
89
|
+
{value &&
|
|
90
|
+
!multiline &&
|
|
91
|
+
rightIcon1 &&
|
|
92
|
+
React.cloneElement(rightIcon1, {
|
|
93
|
+
onPress: handleIconPress1,
|
|
94
|
+
testID: 'icon1',
|
|
95
|
+
})}
|
|
96
|
+
{secureTextEntry &&
|
|
97
|
+
rightIcon2 &&
|
|
98
|
+
React.cloneElement(rightIcon2, {
|
|
99
|
+
onPress: handleIconPress2,
|
|
100
|
+
testID: 'icon2',
|
|
101
|
+
})}
|
|
102
|
+
</View>
|
|
103
|
+
{(error || successMessage) && (
|
|
104
|
+
<CustomTypography
|
|
105
|
+
numberOfLines={2}
|
|
106
|
+
variant="P4regular"
|
|
107
|
+
style={{
|
|
108
|
+
color: successMessage
|
|
109
|
+
? DHRE_COLORS_ALERT.DH_SUCCESS_GREEN
|
|
110
|
+
: DHRE_COLORS_ALERT.DH_ALERT_ORANGE,
|
|
111
|
+
}}
|
|
112
|
+
testID={`${testID}-message`}
|
|
113
|
+
text={successMessage || errorMessage || `Please Enter ${placeholder}`}
|
|
114
|
+
/>
|
|
115
|
+
)}
|
|
116
|
+
</View>
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export default CustomTextInput;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {default} from './CustomInputText';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {TextProps, TextStyle} from 'react-native';
|
|
3
|
+
import {useTheme} from '../../theme/ThemeContext';
|
|
4
|
+
import {withThemeProvider} from '../../theme/withThemeProvider';
|
|
5
|
+
import {FONT_STYLES} from '../../theme/fonts';
|
|
6
|
+
import CustomTypography from '../customTypography/CustomTypography';
|
|
7
|
+
|
|
8
|
+
interface CustomTextProps extends TextProps {
|
|
9
|
+
text: string;
|
|
10
|
+
variant: keyof typeof FONT_STYLES | string;
|
|
11
|
+
style?: TextStyle;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const CustomText: React.FC<CustomTextProps> = ({
|
|
15
|
+
text,
|
|
16
|
+
style,
|
|
17
|
+
variant,
|
|
18
|
+
...props
|
|
19
|
+
}) => {
|
|
20
|
+
const {theme} = useTheme();
|
|
21
|
+
return (
|
|
22
|
+
<CustomTypography
|
|
23
|
+
variant={variant}
|
|
24
|
+
text={text || ''}
|
|
25
|
+
style={[{color: theme.colors.text}, style]}
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default withThemeProvider(CustomText);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {default} from './CustomText';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React, {ReactElement} from 'react';
|
|
2
|
+
import {ViewStyle} from 'react-native';
|
|
3
|
+
|
|
4
|
+
export interface CustomTooltipProps {
|
|
5
|
+
message: string;
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
actionType?: 'press' | 'longPress';
|
|
8
|
+
testId?: string;
|
|
9
|
+
backgroundColor?: string;
|
|
10
|
+
popoverContent?: React.ReactElement;
|
|
11
|
+
icon?: ReactElement;
|
|
12
|
+
iconStyle?: ViewStyle;
|
|
13
|
+
iconColor?: string;
|
|
14
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {StyleSheet} from 'react-native';
|
|
2
|
+
import {DHRE_COLORS_TEXT} from '../../theme/colors';
|
|
3
|
+
import {moderateScale} from '../../utils/stylehelper';
|
|
4
|
+
|
|
5
|
+
const styles = StyleSheet.create({
|
|
6
|
+
tooltipContainerStyle: {
|
|
7
|
+
flex: 1,
|
|
8
|
+
borderRadius: moderateScale(16),
|
|
9
|
+
padding: moderateScale(8),
|
|
10
|
+
},
|
|
11
|
+
mesageContainer: {
|
|
12
|
+
flex: 1,
|
|
13
|
+
flexDirection: 'row',
|
|
14
|
+
justifyContent: 'space-between',
|
|
15
|
+
alignItems: 'center',
|
|
16
|
+
},
|
|
17
|
+
messageStyle: {
|
|
18
|
+
flex: 1,
|
|
19
|
+
color: DHRE_COLORS_TEXT.DH_TEXTDARK,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export default styles;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {Pressable, Text} from 'react-native';
|
|
3
|
+
import {it} from '@jest/globals';
|
|
4
|
+
import {fireEvent, render} from '@testing-library/react-native';
|
|
5
|
+
import CustomTooltip from './CustomTooltip';
|
|
6
|
+
|
|
7
|
+
describe('Custom Tooltip Component', () => {
|
|
8
|
+
it('Component renders correctly', () => {
|
|
9
|
+
const {getByTestId} = render(
|
|
10
|
+
<CustomTooltip message="TEST">
|
|
11
|
+
<Pressable testID="BTN">
|
|
12
|
+
<Text>Press me</Text>
|
|
13
|
+
</Pressable>
|
|
14
|
+
</CustomTooltip>,
|
|
15
|
+
);
|
|
16
|
+
fireEvent.press(getByTestId('BTN'));
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {View} from 'react-native';
|
|
3
|
+
import Tooltip from 'rn-tooltip';
|
|
4
|
+
import CustomTypography from '../customTypography/CustomTypography';
|
|
5
|
+
import {CustomTooltipProps} from './CustomTooltip.interface';
|
|
6
|
+
import styles from './CustomTooltip.styles';
|
|
7
|
+
import {DHRE_COLORS_TEXT} from '../../theme/colors';
|
|
8
|
+
|
|
9
|
+
const CustomTooltip: React.FC<CustomTooltipProps> = ({
|
|
10
|
+
message,
|
|
11
|
+
children,
|
|
12
|
+
actionType = 'press',
|
|
13
|
+
testId = 'CUSTOM-TOOLTIP',
|
|
14
|
+
backgroundColor = DHRE_COLORS_TEXT.DH_WHITE,
|
|
15
|
+
popoverContent,
|
|
16
|
+
icon,
|
|
17
|
+
iconStyle,
|
|
18
|
+
iconColor = DHRE_COLORS_TEXT.DH_BLACK,
|
|
19
|
+
}) => {
|
|
20
|
+
const defaultPopoverContent = (
|
|
21
|
+
<View style={styles.mesageContainer} testID={testId}>
|
|
22
|
+
<CustomTypography
|
|
23
|
+
variant="P4regular"
|
|
24
|
+
style={styles.messageStyle}
|
|
25
|
+
text={message}
|
|
26
|
+
/>
|
|
27
|
+
{icon && (
|
|
28
|
+
<View style={iconStyle}>
|
|
29
|
+
{React.cloneElement(icon, {fill: iconColor})}
|
|
30
|
+
</View>
|
|
31
|
+
)}
|
|
32
|
+
</View>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Tooltip
|
|
37
|
+
containerStyle={styles.tooltipContainerStyle}
|
|
38
|
+
backgroundColor={backgroundColor}
|
|
39
|
+
popover={popoverContent || defaultPopoverContent}
|
|
40
|
+
actionType={actionType}>
|
|
41
|
+
{children}
|
|
42
|
+
</Tooltip>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default CustomTooltip;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {default} from './CustomTooltip';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {FONT_STYLES} from '../../theme/fonts';
|
|
3
|
+
import {Text, TextProps} from 'react-native';
|
|
4
|
+
|
|
5
|
+
interface TypoTextProps extends TextProps {
|
|
6
|
+
variant: keyof typeof FONT_STYLES | string;
|
|
7
|
+
text?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const CustomTypography: React.FC<TypoTextProps> = ({
|
|
11
|
+
variant,
|
|
12
|
+
style,
|
|
13
|
+
text,
|
|
14
|
+
...props
|
|
15
|
+
}) => {
|
|
16
|
+
const textStyle = FONT_STYLES[variant];
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Text testID="Typo-Text" style={[textStyle, style]} {...props}>
|
|
20
|
+
{text}
|
|
21
|
+
</Text>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default CustomTypography;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {DHRE_COLORS_PRIMARY, DHRE_COLORS_TEXT} from '../../theme/colors';
|
|
2
|
+
import {horizontalScale, verticalScale} from '../../utils/stylehelper';
|
|
3
|
+
import {StyleSheet} from 'react-native';
|
|
4
|
+
|
|
5
|
+
export const styles = StyleSheet.create({
|
|
6
|
+
container: {
|
|
7
|
+
backgroundColor: DHRE_COLORS_TEXT.DH_BLACK,
|
|
8
|
+
paddingHorizontal: horizontalScale(16),
|
|
9
|
+
paddingVertical: verticalScale(24),
|
|
10
|
+
width: verticalScale(327),
|
|
11
|
+
alignItems: 'center',
|
|
12
|
+
justifyContent: 'center',
|
|
13
|
+
},
|
|
14
|
+
content: {
|
|
15
|
+
alignItems: 'center',
|
|
16
|
+
},
|
|
17
|
+
title: {
|
|
18
|
+
color: DHRE_COLORS_TEXT.DH_TEXTDARK,
|
|
19
|
+
marginTop: verticalScale(16),
|
|
20
|
+
},
|
|
21
|
+
description: {
|
|
22
|
+
color: DHRE_COLORS_TEXT.DH_TEXTLIGHT,
|
|
23
|
+
textAlign: 'center',
|
|
24
|
+
marginTop: verticalScale(16),
|
|
25
|
+
},
|
|
26
|
+
browse: {
|
|
27
|
+
color: DHRE_COLORS_PRIMARY.DH_RED_100,
|
|
28
|
+
textDecorationLine: 'underline',
|
|
29
|
+
},
|
|
30
|
+
button: {
|
|
31
|
+
backgroundColor: DHRE_COLORS_TEXT.DH_BLACK,
|
|
32
|
+
padding: verticalScale(12),
|
|
33
|
+
borderRadius: 20,
|
|
34
|
+
width: '40%',
|
|
35
|
+
marginTop: verticalScale(16),
|
|
36
|
+
},
|
|
37
|
+
buttonText: {
|
|
38
|
+
color: DHRE_COLORS_TEXT.DH_WHITE,
|
|
39
|
+
textAlign: 'center',
|
|
40
|
+
},
|
|
41
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {render, fireEvent} from '@testing-library/react-native';
|
|
3
|
+
import FileUpload from './FileUpload';
|
|
4
|
+
|
|
5
|
+
describe('FileUpload component', () => {
|
|
6
|
+
it('renders correctly', () => {
|
|
7
|
+
const onUploadMock = jest.fn();
|
|
8
|
+
const {getByTestId} = render(
|
|
9
|
+
<FileUpload
|
|
10
|
+
onUpload={onUploadMock}
|
|
11
|
+
containerStyle={{}}
|
|
12
|
+
btnText={'upload'}
|
|
13
|
+
uploadImageStyling={{}}
|
|
14
|
+
title="Upload Image"
|
|
15
|
+
/>,
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
expect(getByTestId('file-upload-container')).toBeTruthy();
|
|
19
|
+
expect(getByTestId('file-upload-image')).toBeTruthy();
|
|
20
|
+
expect(getByTestId('file-upload-button')).toBeTruthy();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('calls onUpload when button is pressed', () => {
|
|
24
|
+
const onUploadMock = jest.fn();
|
|
25
|
+
const {getByTestId} = render(
|
|
26
|
+
<FileUpload
|
|
27
|
+
onUpload={onUploadMock}
|
|
28
|
+
containerStyle={{}}
|
|
29
|
+
btnText={'upload'}
|
|
30
|
+
uploadImageStyling={{}}
|
|
31
|
+
title="Upload Image"
|
|
32
|
+
/>,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const button = getByTestId('file-upload-button');
|
|
36
|
+
fireEvent.press(button);
|
|
37
|
+
expect(onUploadMock).toHaveBeenCalledTimes(1);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {View, Pressable, ViewStyle, ImageStyle} from 'react-native';
|
|
3
|
+
import CustomTypography from '../customTypography/CustomTypography';
|
|
4
|
+
import {styles} from './FileUpload.styles';
|
|
5
|
+
|
|
6
|
+
interface FileUploadProps {
|
|
7
|
+
onUpload: () => void;
|
|
8
|
+
title: string;
|
|
9
|
+
containerStyle?: ViewStyle;
|
|
10
|
+
btnText: string;
|
|
11
|
+
uploadImageStyling: ImageStyle;
|
|
12
|
+
icon?: React.ReactElement;
|
|
13
|
+
iconStyle?: ViewStyle;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const FileUpload: React.FC<FileUploadProps> = ({
|
|
17
|
+
onUpload,
|
|
18
|
+
title,
|
|
19
|
+
containerStyle,
|
|
20
|
+
btnText,
|
|
21
|
+
uploadImageStyling,
|
|
22
|
+
icon,
|
|
23
|
+
iconStyle,
|
|
24
|
+
}) => {
|
|
25
|
+
return (
|
|
26
|
+
<View
|
|
27
|
+
style={[styles.container, containerStyle]}
|
|
28
|
+
testID="file-upload-container">
|
|
29
|
+
<View style={styles.content}>
|
|
30
|
+
<View style={[uploadImageStyling]} testID="file-upload-image">
|
|
31
|
+
{icon && React.cloneElement(icon, {style: [iconStyle]})}
|
|
32
|
+
</View>
|
|
33
|
+
<CustomTypography variant="H8bold" style={styles.title} text={title} />
|
|
34
|
+
<CustomTypography
|
|
35
|
+
variant="P4regular"
|
|
36
|
+
style={styles.description}
|
|
37
|
+
text={`Drop files directly here or `}
|
|
38
|
+
/>
|
|
39
|
+
<CustomTypography
|
|
40
|
+
variant="P4regular"
|
|
41
|
+
style={styles.browse}
|
|
42
|
+
text={btnText}
|
|
43
|
+
/>
|
|
44
|
+
<CustomTypography
|
|
45
|
+
testID="file-upload-description"
|
|
46
|
+
variant="P4regular"
|
|
47
|
+
style={styles.description}
|
|
48
|
+
text={` from your device`}
|
|
49
|
+
/>
|
|
50
|
+
</View>
|
|
51
|
+
<Pressable
|
|
52
|
+
style={styles.button}
|
|
53
|
+
onPress={onUpload}
|
|
54
|
+
testID="file-upload-button">
|
|
55
|
+
<CustomTypography
|
|
56
|
+
variant="B2semiBold"
|
|
57
|
+
style={styles.buttonText}
|
|
58
|
+
text={btnText}
|
|
59
|
+
/>
|
|
60
|
+
</Pressable>
|
|
61
|
+
</View>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default FileUpload;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {default} from './FileUpload';
|