@holper/react-native-holper-storybook 0.6.101 → 0.7.0

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 (210) hide show
  1. package/.expo/README.md +8 -0
  2. package/.nvmrc +1 -0
  3. package/.prettierignore +5 -0
  4. package/.storybook/index.jsx +11 -0
  5. package/.storybook/main.js +8 -0
  6. package/.storybook/preview.jsx +51 -0
  7. package/.storybook/storybook.requires.js +43 -0
  8. package/.yarn/releases/yarn-4.5.0.cjs +925 -0
  9. package/.yarnrc.yml +3 -0
  10. package/App.jsx +29 -0
  11. package/LICENSE +21 -0
  12. package/{readme.md → README.md} +18 -19
  13. package/app.config.js +77 -0
  14. package/assets/adaptive-icon.png +0 -0
  15. package/assets/favicon.png +0 -0
  16. package/assets/fonts/Poppins-Bold.ttf +0 -0
  17. package/assets/fonts/Poppins-Regular.ttf +0 -0
  18. package/assets/fonts/Poppins-SemiBold.ttf +0 -0
  19. package/assets/icon.png +0 -0
  20. package/assets/splash.png +0 -0
  21. package/babel.config.js +7 -0
  22. package/build.sh +11 -0
  23. package/components/Button/index.tsx +66 -0
  24. package/{lib/components/Button/style.js → components/Button/style.ts} +8 -7
  25. package/components/Card/index.tsx +33 -0
  26. package/{lib/components/Card/style.js → components/Card/style.ts} +5 -4
  27. package/{lib/components/ConfirmationModal/index.js → components/ConfirmationModal/index.tsx} +25 -79
  28. package/{lib/components/ConfirmationModal/style.js → components/ConfirmationModal/style.tsx} +14 -13
  29. package/{lib/components/Container/index.js → components/Container/index.tsx} +7 -28
  30. package/{lib/components/Container/style.js → components/Container/style.ts} +6 -5
  31. package/{lib/components/CustomChatView/index.js → components/CustomChatView/index.tsx} +22 -30
  32. package/{lib/components/CustomChatView/style.js → components/CustomChatView/style.ts} +1 -1
  33. package/components/DeckSwiper/index.tsx +90 -0
  34. package/{lib/components/DeckSwiper/style.js → components/DeckSwiper/style.ts} +13 -12
  35. package/components/DonutCountdown/index.tsx +86 -0
  36. package/components/DonutCountdown/style.ts +8 -0
  37. package/components/FloatingContainer/index.tsx +35 -0
  38. package/{lib/components/FloatingContainer/style.js → components/FloatingContainer/style.ts} +7 -6
  39. package/components/Footer/index.tsx +35 -0
  40. package/{lib/components/Footer/style.js → components/Footer/style.ts} +4 -3
  41. package/components/Header/index.tsx +21 -0
  42. package/{lib/components/Header/style.js → components/Header/style.ts} +4 -3
  43. package/{lib/components/ImagePicker/index.js → components/ImagePicker/index.tsx} +3 -12
  44. package/components/ImageResponsive/index.tsx +24 -0
  45. package/components/ImageResponsive/style.ts +9 -0
  46. package/components/ImageViewer/index.tsx +36 -0
  47. package/{lib/components/ImageViewer/style.js → components/ImageViewer/style.ts} +11 -10
  48. package/{lib/components/Input/index.js → components/Input/index.tsx} +6 -33
  49. package/{lib/components/Input/style.js → components/Input/style.ts} +7 -18
  50. package/{lib/components/InputPin/index.js → components/InputPin/index.tsx} +6 -13
  51. package/{lib/components/InputPin/style.js → components/InputPin/style.ts} +7 -6
  52. package/components/MenuItem/index.tsx +25 -0
  53. package/{lib/components/MenuItem/style.js → components/MenuItem/style.ts} +9 -7
  54. package/{lib/components/NavigationTitle/index.js → components/NavigationTitle/index.tsx} +9 -30
  55. package/{lib/components/NavigationTitle/style.js → components/NavigationTitle/style.ts} +12 -11
  56. package/components/Notification/index.tsx +44 -0
  57. package/{lib/components/Notification/style.js → components/Notification/style.ts} +13 -11
  58. package/components/PreventDoubleClick/index.tsx +28 -0
  59. package/components/Select/index.tsx +51 -0
  60. package/components/Select/style.ts +64 -0
  61. package/{lib/components/SwipeablePanel/index.js → components/SwipeablePanel/index.tsx} +58 -85
  62. package/{lib/components/SwipeablePanel/style.js → components/SwipeablePanel/style.ts} +15 -14
  63. package/components/Switch/index.tsx +30 -0
  64. package/components/TakePicture/confirmPictureModal.tsx +37 -0
  65. package/components/TakePicture/index.tsx +148 -0
  66. package/{lib/components/TakePicture/style.js → components/TakePicture/style.ts} +4 -4
  67. package/components/Text/index.tsx +33 -0
  68. package/{lib/components/Text/style.js → components/Text/style.ts} +4 -2
  69. package/{lib/components/Textarea/index.js → components/Textarea/index.tsx} +5 -24
  70. package/{lib/components/Textarea/style.js → components/Textarea/style.ts} +5 -4
  71. package/components/TimeOutButton/index.tsx +67 -0
  72. package/{lib/components/TimeOutButton/style.js → components/TimeOutButton/style.ts} +4 -3
  73. package/components/Toast/index.tsx +34 -0
  74. package/components/Toast/style.ts +12 -0
  75. package/{lib/components/UploadDocument/index.js → components/UploadDocument/index.tsx} +49 -105
  76. package/{lib/components/UploadDocument/style.js → components/UploadDocument/style.ts} +16 -15
  77. package/components/VirtualKeyboard/index.tsx +75 -0
  78. package/{lib/components/VirtualKeyboard/style.js → components/VirtualKeyboard/style.ts} +9 -8
  79. package/components/index.ts +29 -0
  80. package/{lib/configs/constants.js → configs/constants.ts} +50 -48
  81. package/configs/types.ts +326 -0
  82. package/eas.json +27 -0
  83. package/eslint.config.mjs +205 -0
  84. package/hooks/index.ts +2 -0
  85. package/{lib/hooks/useDebounce.js → hooks/useDebounce.tsx} +6 -4
  86. package/hooks/useLoadFonts.tsx +13 -0
  87. package/index.js +3 -2
  88. package/lib/components/Button/index.tsx +66 -0
  89. package/lib/components/Button/style.ts +111 -0
  90. package/lib/components/Card/index.tsx +33 -0
  91. package/lib/components/Card/style.ts +34 -0
  92. package/lib/components/ConfirmationModal/index.tsx +104 -0
  93. package/lib/components/ConfirmationModal/style.tsx +53 -0
  94. package/lib/components/Container/index.tsx +33 -0
  95. package/lib/components/Container/style.ts +13 -0
  96. package/lib/components/CustomChatView/index.tsx +65 -0
  97. package/lib/components/CustomChatView/style.ts +10 -0
  98. package/lib/components/DeckSwiper/index.tsx +90 -0
  99. package/lib/components/DeckSwiper/style.ts +59 -0
  100. package/lib/components/DonutCountdown/index.tsx +86 -0
  101. package/lib/components/DonutCountdown/style.ts +8 -0
  102. package/lib/components/FloatingContainer/index.tsx +35 -0
  103. package/lib/components/FloatingContainer/style.ts +25 -0
  104. package/lib/components/Footer/index.tsx +35 -0
  105. package/lib/components/Footer/style.ts +40 -0
  106. package/lib/components/Header/index.tsx +21 -0
  107. package/lib/components/Header/style.ts +34 -0
  108. package/lib/components/ImagePicker/index.tsx +18 -0
  109. package/lib/components/ImageResponsive/index.tsx +24 -0
  110. package/lib/components/ImageResponsive/style.ts +9 -0
  111. package/lib/components/ImageViewer/index.tsx +36 -0
  112. package/lib/components/ImageViewer/style.ts +38 -0
  113. package/lib/components/Input/index.tsx +62 -0
  114. package/lib/components/Input/style.ts +91 -0
  115. package/lib/components/InputPin/index.tsx +21 -0
  116. package/lib/components/InputPin/style.ts +22 -0
  117. package/lib/components/MenuItem/index.tsx +25 -0
  118. package/lib/components/MenuItem/style.ts +44 -0
  119. package/lib/components/NavigationTitle/index.tsx +53 -0
  120. package/lib/components/NavigationTitle/style.ts +49 -0
  121. package/lib/components/Notification/index.tsx +44 -0
  122. package/lib/components/Notification/style.ts +50 -0
  123. package/lib/components/PreventDoubleClick/index.tsx +28 -0
  124. package/lib/components/Select/index.tsx +51 -0
  125. package/lib/components/Select/style.ts +64 -0
  126. package/lib/components/SwipeablePanel/index.tsx +208 -0
  127. package/lib/components/SwipeablePanel/style.ts +81 -0
  128. package/lib/components/Switch/index.tsx +30 -0
  129. package/lib/components/TakePicture/confirmPictureModal.tsx +37 -0
  130. package/lib/components/TakePicture/index.tsx +148 -0
  131. package/lib/components/TakePicture/style.ts +95 -0
  132. package/lib/components/Text/index.tsx +33 -0
  133. package/lib/components/Text/style.ts +101 -0
  134. package/lib/components/Textarea/index.tsx +26 -0
  135. package/lib/components/Textarea/style.ts +38 -0
  136. package/lib/components/TimeOutButton/index.tsx +67 -0
  137. package/lib/components/TimeOutButton/style.ts +42 -0
  138. package/lib/components/Toast/index.tsx +34 -0
  139. package/lib/components/Toast/style.ts +12 -0
  140. package/lib/components/UploadDocument/index.tsx +179 -0
  141. package/lib/components/UploadDocument/style.ts +57 -0
  142. package/lib/components/VirtualKeyboard/index.tsx +75 -0
  143. package/lib/components/VirtualKeyboard/style.ts +25 -0
  144. package/lib/components/index.ts +29 -0
  145. package/lib/configs/constants.ts +273 -0
  146. package/lib/configs/types.ts +326 -0
  147. package/lib/hooks/index.ts +2 -0
  148. package/lib/hooks/useDebounce.tsx +24 -0
  149. package/lib/hooks/useLoadFonts.tsx +13 -0
  150. package/lib/index.js +3 -2
  151. package/metro.config.js +11 -0
  152. package/package.json +72 -63
  153. package/prettier.config.mjs +23 -0
  154. package/stories/Button.stories.tsx +181 -0
  155. package/stories/Card.stories.tsx +22 -0
  156. package/stories/Colors.stories.tsx +57 -0
  157. package/stories/ConfirmationModal.stories.tsx +142 -0
  158. package/stories/Container.stories.tsx +105 -0
  159. package/stories/DeckSwiper.stories.tsx +43 -0
  160. package/stories/DonutCountdown.stories.tsx +134 -0
  161. package/stories/FloatingContainer.stories.tsx +139 -0
  162. package/stories/Footer.stories.tsx +65 -0
  163. package/stories/Header.stories.tsx +37 -0
  164. package/stories/ImagePicker.stories.tsx +14 -0
  165. package/stories/ImageResponsive.stories.tsx +18 -0
  166. package/stories/ImageViewer.stories.tsx +24 -0
  167. package/stories/Input.stories.tsx +119 -0
  168. package/stories/InputPin.stories.tsx +40 -0
  169. package/stories/Menu.stories.tsx +53 -0
  170. package/stories/MenuItem.stories.tsx +30 -0
  171. package/stories/NavigationTitle.stories.tsx +51 -0
  172. package/stories/Notification.stories.tsx +58 -0
  173. package/stories/Select.stories.tsx +270 -0
  174. package/stories/SwipeablePanel.stories.tsx +360 -0
  175. package/stories/Switch.stories.tsx +36 -0
  176. package/stories/TakePicture.stories.tsx +59 -0
  177. package/stories/Text.stories.tsx +61 -0
  178. package/stories/Textarea.stories.tsx +48 -0
  179. package/stories/TimeOutButton.stories.tsx +55 -0
  180. package/stories/Toast.stories.tsx +37 -0
  181. package/stories/UploadDocument.stories.tsx +179 -0
  182. package/stories/VirtualKeyboard.stories.tsx +14 -0
  183. package/tsconfig.json +21 -0
  184. package/utilities/ScrollView.tsx +19 -0
  185. package/utilities/index.ts +2 -0
  186. package/utilities/utils.ts +29 -0
  187. package/lib/components/Button/index.js +0 -104
  188. package/lib/components/Card/index.js +0 -49
  189. package/lib/components/DeckSwiper/index.js +0 -118
  190. package/lib/components/FlashMessage/index.js +0 -81
  191. package/lib/components/FloatingContainer/index.js +0 -69
  192. package/lib/components/Footer/index.js +0 -61
  193. package/lib/components/Header/index.js +0 -45
  194. package/lib/components/ImageResponsive/index.js +0 -39
  195. package/lib/components/ImageResponsive/style.js +0 -7
  196. package/lib/components/ImageViewer/index.js +0 -62
  197. package/lib/components/MenuItem/index.js +0 -44
  198. package/lib/components/Notification/index.js +0 -80
  199. package/lib/components/PreventDoubleClick/index.js +0 -21
  200. package/lib/components/Select/index.js +0 -89
  201. package/lib/components/Select/style.js +0 -81
  202. package/lib/components/Switch/index.js +0 -57
  203. package/lib/components/TakePicture/confirmPictureModal.js +0 -64
  204. package/lib/components/TakePicture/index.js +0 -198
  205. package/lib/components/Text/index.js +0 -75
  206. package/lib/components/TimeOutButton/index.js +0 -104
  207. package/lib/components/VirtualKeyboard/index.js +0 -86
  208. package/lib/components/index.js +0 -28
  209. package/lib/configs/loadFonts.js +0 -11
  210. package/lib/hooks/index.js +0 -1
@@ -0,0 +1,101 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ import { Colors } from '../../configs/constants';
4
+
5
+ export default StyleSheet.create({
6
+ // colors
7
+ dark: {
8
+ color: Colors.darkblue,
9
+ },
10
+ light: {
11
+ color: Colors.dimgray,
12
+ },
13
+ lighter: {
14
+ color: Colors.lightblue,
15
+ },
16
+ white: {
17
+ color: Colors.white,
18
+ },
19
+ green: {
20
+ color: Colors.green,
21
+ },
22
+ red: {
23
+ color: Colors.red,
24
+ },
25
+ yellow: {
26
+ color: Colors.yellow,
27
+ },
28
+ violet: {
29
+ color: Colors.violet,
30
+ },
31
+ brightblue: {
32
+ color: Colors.brightblue,
33
+ },
34
+ lightgold: {
35
+ color: Colors.lightgold,
36
+ },
37
+ darkyellow: {
38
+ color: Colors.darkyellow,
39
+ },
40
+ gold: {
41
+ color: Colors.gold,
42
+ },
43
+ brightviolet: {
44
+ color: Colors.brightviolet,
45
+ },
46
+ electricblue: {
47
+ color: Colors.electricblue,
48
+ },
49
+ midgreen: {
50
+ color: Colors.midgreen,
51
+ },
52
+ // variants
53
+ lowercase: {
54
+ textTransform: 'lowercase',
55
+ },
56
+ uppercase: {
57
+ textTransform: 'uppercase',
58
+ },
59
+ // sizes
60
+ tiny: {
61
+ fontSize: 10,
62
+ },
63
+ small: {
64
+ fontSize: 12,
65
+ },
66
+ medium: {
67
+ fontSize: 14,
68
+ },
69
+ large: {
70
+ fontSize: 18,
71
+ },
72
+ 'extra-large': {
73
+ fontSize: 24,
74
+ },
75
+ huge: {
76
+ fontSize: 40,
77
+ },
78
+ // Weights
79
+ regular: {
80
+ fontFamily: 'poppins_regular',
81
+ },
82
+ bold: {
83
+ fontFamily: 'poppins_bold',
84
+ },
85
+ semiBold: {
86
+ fontFamily: 'poppins_semiBold',
87
+ },
88
+ // Align
89
+ left: {
90
+ textAlign: 'left',
91
+ },
92
+ center: {
93
+ textAlign: 'center',
94
+ },
95
+ right: {
96
+ textAlign: 'right',
97
+ },
98
+ justify: {
99
+ textAlign: 'justify',
100
+ },
101
+ });
@@ -0,0 +1,26 @@
1
+ import { TextInput } from 'react-native';
2
+
3
+ import { Colors } from '../../configs/constants';
4
+ import style from './style';
5
+
6
+ import type { TextareaProps } from '../../configs/types';
7
+
8
+ const Textarea = ({ variant = 'default', disabled, numberOfLines = 4, fitToContainer, ...props }: TextareaProps) => (
9
+ <TextInput
10
+ style={[
11
+ style.textarea,
12
+ fitToContainer ? style.fitToContainer : style.textAreaDefaultWidth,
13
+ { height: numberOfLines * 25 },
14
+ style[variant],
15
+ disabled ? style.disabled : {},
16
+ ]}
17
+ multiline
18
+ editable={!disabled}
19
+ numberOfLines={numberOfLines}
20
+ textAlignVertical="top"
21
+ placeholderTextColor={Colors.midblue}
22
+ {...props}
23
+ />
24
+ );
25
+
26
+ export default Textarea;
@@ -0,0 +1,38 @@
1
+ import { Dimensions, StyleSheet } from 'react-native';
2
+
3
+ import { borderRadius, Colors } from '../../configs/constants';
4
+
5
+ const { width } = Dimensions.get('window');
6
+
7
+ export default StyleSheet.create({
8
+ textarea: {
9
+ borderRadius,
10
+ borderWidth: 1,
11
+ paddingHorizontal: 10,
12
+ paddingVertical: 10,
13
+ color: Colors.darkblue,
14
+ fontFamily: 'poppins_regular',
15
+ backgroundColor: Colors.white,
16
+ textAlignVertical: 'center',
17
+ marginVertical: 6,
18
+ },
19
+ textAreaDefaultWidth: {
20
+ width: width - 80,
21
+ },
22
+ fitToContainer: {
23
+ width: '100%',
24
+ },
25
+ default: {
26
+ borderColor: Colors.midblue,
27
+ },
28
+ completed: {
29
+ borderColor: Colors.green,
30
+ },
31
+ error: {
32
+ borderColor: Colors.red,
33
+ color: Colors.red,
34
+ },
35
+ disabled: {
36
+ opacity: 0.5,
37
+ },
38
+ });
@@ -0,0 +1,67 @@
1
+ import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
2
+ import { Dimensions, TouchableOpacity, View } from 'react-native';
3
+
4
+ import style from './style';
5
+
6
+ import type { TimeOutButtonProps } from '../../configs/types';
7
+
8
+ const { width } = Dimensions.get('window');
9
+ const BUTTON_WIDTH = width * 0.6;
10
+
11
+ const TimeOutButton = forwardRef(({ onPress, time = 3000, warning, children }: TimeOutButtonProps, ref) => {
12
+ const [elapsedTime, setElapsedTime] = useState<number>(0);
13
+ const [interval, setLocalInterval] = useState<NodeJS.Timeout | undefined>(undefined);
14
+
15
+ useEffect(() => {
16
+ let isCancelled = false;
17
+ const timer = setInterval(() => {
18
+ if (!isCancelled) {
19
+ setElapsedTime((prevElapsedTime) => prevElapsedTime + 1);
20
+ }
21
+ }, 1);
22
+ setLocalInterval(timer);
23
+
24
+ return () => {
25
+ clearInterval(timer);
26
+ isCancelled = true;
27
+ };
28
+ }, []);
29
+
30
+ useImperativeHandle(ref, () => ({
31
+ onStop() {
32
+ clearInterval(interval);
33
+ },
34
+ }));
35
+
36
+ const watchInterval = () => {
37
+ if (elapsedTime >= time) {
38
+ clearInterval(interval);
39
+ if (onPress) onPress();
40
+ }
41
+
42
+ return elapsedTime <= time ? (BUTTON_WIDTH * (time - elapsedTime)) / time : BUTTON_WIDTH;
43
+ };
44
+
45
+ const checkWarningPercent = () => (elapsedTime <= time ? time * 0.3 > time - elapsedTime : false);
46
+
47
+ const onLocalPress = () => {
48
+ setElapsedTime(time);
49
+ clearInterval(interval);
50
+ if (onPress) onPress();
51
+ };
52
+
53
+ return (
54
+ <TouchableOpacity style={[style.button, style.buttonBg]} onPress={onLocalPress}>
55
+ <View
56
+ style={[
57
+ style.button,
58
+ warning ? (checkWarningPercent() ? style.buttonOverlayWarning : style.buttonOverlay) : style.buttonOverlay,
59
+ { width: watchInterval() },
60
+ ]}
61
+ />
62
+ {children}
63
+ </TouchableOpacity>
64
+ );
65
+ });
66
+
67
+ export default TimeOutButton;
@@ -0,0 +1,42 @@
1
+ import { Dimensions, StyleSheet } from 'react-native';
2
+
3
+ import { Colors } from '../../configs/constants';
4
+
5
+ const { width } = Dimensions.get('window');
6
+
7
+ export default StyleSheet.create({
8
+ // Default button shape
9
+ button: {
10
+ margin: 8,
11
+ height: 50,
12
+ overflow: 'hidden',
13
+ },
14
+ // Button background
15
+ buttonBg: {
16
+ borderRadius: 10,
17
+ width: width * 0.6,
18
+ justifyContent: 'center',
19
+ alignItems: 'center',
20
+ paddingVertical: 6,
21
+ paddingHorizontal: 8,
22
+ borderWidth: 1,
23
+ borderColor: Colors.lightgreen,
24
+ backgroundColor: Colors.lightgreen,
25
+ shadowColor: Colors.lightgreen,
26
+ shadowOffset: { width: 0, height: 4 },
27
+ shadowOpacity: 0.4,
28
+ shadowRadius: 3,
29
+ elevation: 5,
30
+ },
31
+ // Button overlays
32
+ buttonOverlay: {
33
+ position: 'absolute',
34
+ left: -10,
35
+ backgroundColor: Colors.green,
36
+ },
37
+ buttonOverlayWarning: {
38
+ position: 'absolute',
39
+ left: -10,
40
+ backgroundColor: Colors.red,
41
+ },
42
+ });
@@ -0,0 +1,34 @@
1
+ import { Ionicons } from '@expo/vector-icons';
2
+ import { toast, Toaster } from 'sonner-native';
3
+
4
+ import { Colors } from '../../configs/constants';
5
+ import style from './style';
6
+
7
+ import type { ToastMessageProps } from '../../configs/types';
8
+
9
+ const Toast = () => (
10
+ <Toaster
11
+ autoWiggleOnUpdate="toast-change"
12
+ closeButton
13
+ duration={3000}
14
+ icons={{
15
+ error: <Ionicons name="alert-circle-outline" color={Colors.darkred} size={30} />,
16
+ success: <Ionicons name="checkmark-circle-outline" color={Colors.darkgreen} size={30} />,
17
+ }}
18
+ pauseWhenPageIsHidden
19
+ position="top-center"
20
+ richColors
21
+ swipeToDismissDirection="up"
22
+ visibleToasts={4}
23
+ toastOptions={{
24
+ titleStyle: style.titleStyle,
25
+ descriptionStyle: style.descriptionStyle,
26
+ }}
27
+ />
28
+ );
29
+
30
+ export const sendMessage = ({ variant, message, description }: ToastMessageProps) => {
31
+ toast[variant](message, { description });
32
+ };
33
+
34
+ export default Toast;
@@ -0,0 +1,12 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ export default StyleSheet.create({
4
+ titleStyle: {
5
+ fontSize: 14,
6
+ fontFamily: 'poppins_semiBold',
7
+ },
8
+ descriptionStyle: {
9
+ fontSize: 14,
10
+ fontFamily: 'poppins_regular',
11
+ },
12
+ });
@@ -0,0 +1,179 @@
1
+ import * as ExpoImagePicker from 'expo-image-picker';
2
+ import * as MediaLibrary from 'expo-media-library';
3
+ import { useEffect, useState } from 'react';
4
+ import { ActivityIndicator, Platform, TouchableOpacity, View } from 'react-native';
5
+
6
+ import { Colors } from '../../configs/constants';
7
+ import Button from '../Button';
8
+ import ConfirmationModal from '../ConfirmationModal';
9
+ import ImagePicker from '../ImagePicker';
10
+ import ImageViewer from '../ImageViewer';
11
+ import TakePicture from '../TakePicture';
12
+ import Text from '../Text';
13
+ import style from './style';
14
+
15
+ import type { UploadDocumentProps } from '../../configs/types';
16
+
17
+ const iOS = Platform.OS === 'ios';
18
+
19
+ const UploadDocument = ({
20
+ title,
21
+ description,
22
+ icon,
23
+ completed,
24
+ isAvatarPicker,
25
+ uploadButtonText,
26
+ reUploadButtonText,
27
+ mediaModal,
28
+ takePicture,
29
+ inverted,
30
+ onSelectImage,
31
+ file,
32
+ onPermissionDenied,
33
+ }: UploadDocumentProps) => {
34
+ const [showMediaModal, setShowMediaModal] = useState<boolean>(false);
35
+ const [showCamera, setShowCamera] = useState<boolean>(false);
36
+ const [image, setImage] = useState<string | { uri: string }>();
37
+ const [loading, setLoading] = useState<boolean>(true);
38
+
39
+ useEffect(() => {
40
+ (async () => {
41
+ if (iOS) {
42
+ await MediaLibrary.requestPermissionsAsync();
43
+ } else {
44
+ await ExpoImagePicker.getMediaLibraryPermissionsAsync();
45
+ }
46
+ })();
47
+ }, []);
48
+
49
+ useEffect(() => {
50
+ if (!image) {
51
+ setImage(file);
52
+ }
53
+ }, [file, image]);
54
+
55
+ interface PickUploadMethodParams {
56
+ method: 'camera' | 'gallery' | string;
57
+ }
58
+
59
+ interface GalleryPermissionResult {
60
+ status: string;
61
+ }
62
+
63
+ const pickUploadMethod = async (method: PickUploadMethodParams['method']): Promise<void> => {
64
+ setShowMediaModal(false);
65
+
66
+ switch (method) {
67
+ case 'camera':
68
+ setTimeout(async () => {
69
+ setShowCamera(true);
70
+ }, 500);
71
+ break;
72
+ case 'gallery':
73
+ setTimeout(async () => {
74
+ const { status: galleryStatus }: GalleryPermissionResult = iOS
75
+ ? await MediaLibrary.requestPermissionsAsync()
76
+ : await ExpoImagePicker.getMediaLibraryPermissionsAsync();
77
+
78
+ if (galleryStatus !== 'granted' && iOS) {
79
+ if (onPermissionDenied) {
80
+ onPermissionDenied();
81
+ }
82
+ return;
83
+ }
84
+
85
+ const pickedImage = await ImagePicker(isAvatarPicker);
86
+ if (pickedImage !== undefined) {
87
+ selectImage(pickedImage);
88
+ }
89
+ }, 500);
90
+ break;
91
+ default:
92
+ break;
93
+ }
94
+ };
95
+
96
+ const selectImage = (selectedImage: any) => {
97
+ setImage(selectedImage);
98
+ if (onSelectImage) {
99
+ onSelectImage(selectedImage);
100
+ }
101
+ };
102
+
103
+ return (
104
+ <View style={[style.container, completed ? style.containerCompleted : {}]}>
105
+ {image ? (
106
+ <View style={style.uploadedContainer}>
107
+ <View>
108
+ <ImageViewer
109
+ source={{
110
+ uri: typeof image === 'object' ? image.uri : image,
111
+ }}
112
+ style={style.image}
113
+ resizeMode="cover"
114
+ avatar
115
+ onLoadEnd={() => setLoading(false)}
116
+ />
117
+ {loading && <ActivityIndicator style={style.imageSpinner} animating={loading} color={Colors.darkblue} />}
118
+ </View>
119
+ <View style={style.reUploadButtons}>
120
+ <Text style={style.titleUploaded} numberOfLines={1} ellipsizeMode="tail">
121
+ {title}
122
+ </Text>
123
+ <TouchableOpacity onPress={() => setShowMediaModal(true)}>
124
+ <Text size="tiny" style={style.reUpload}>
125
+ {reUploadButtonText}
126
+ </Text>
127
+ </TouchableOpacity>
128
+ </View>
129
+ </View>
130
+ ) : (
131
+ <View style={style.noUploaded}>
132
+ {icon}
133
+ <Text size="large" style={style.title} numberOfLines={1} ellipsizeMode="tail">
134
+ {title}
135
+ </Text>
136
+ <Text size="small" style={style.description}>
137
+ {description}
138
+ </Text>
139
+ <Button variant={inverted ? 'inverted' : 'primary'} onPress={() => setShowMediaModal(true)}>
140
+ <Text color="white">{uploadButtonText}</Text>
141
+ </Button>
142
+ </View>
143
+ )}
144
+
145
+ <ConfirmationModal
146
+ visible={showMediaModal}
147
+ inverted={inverted}
148
+ title={mediaModal.title}
149
+ onConfirm={() => pickUploadMethod('camera')}
150
+ confirmText={mediaModal.confirmText}
151
+ onCancel={() => pickUploadMethod('gallery')}
152
+ cancelText={mediaModal.cancelText}
153
+ onClose={() => setShowMediaModal(false)}
154
+ >
155
+ <Text>{mediaModal.description}</Text>
156
+ </ConfirmationModal>
157
+
158
+ <TakePicture
159
+ visible={showCamera}
160
+ cameraErrorMessage={takePicture.cameraErrorMessage}
161
+ requestPermissionsMessage={takePicture.requestPermissionsMessage}
162
+ processingPictureMessage={takePicture.processingPictureMessage}
163
+ repeatPictureText={takePicture.repeatPictureText}
164
+ usePictureText={takePicture.usePictureText}
165
+ avatar={isAvatarPicker}
166
+ onClose={(selectedImage) => {
167
+ if (selectedImage) {
168
+ selectImage(selectedImage);
169
+ }
170
+ setTimeout(() => {
171
+ setShowCamera(false);
172
+ }, 0);
173
+ }}
174
+ />
175
+ </View>
176
+ );
177
+ };
178
+
179
+ export default UploadDocument;
@@ -0,0 +1,57 @@
1
+ import { Dimensions, StyleSheet } from 'react-native';
2
+
3
+ import { Colors } from '../../configs/constants';
4
+
5
+ const { width } = Dimensions.get('window');
6
+
7
+ export default StyleSheet.create({
8
+ container: {
9
+ borderWidth: 1,
10
+ borderColor: Colors.dimgray,
11
+ borderRadius: 15,
12
+ width: width - 80,
13
+ padding: 15,
14
+ justifyContent: 'center',
15
+ overflow: 'hidden',
16
+ },
17
+ containerCompleted: {
18
+ borderColor: Colors.green,
19
+ },
20
+ noUploaded: {
21
+ alignItems: 'center',
22
+ },
23
+ title: {
24
+ marginTop: 5,
25
+ },
26
+ titleUploaded: {
27
+ marginTop: 5,
28
+ width: width - 225,
29
+ },
30
+ description: {
31
+ marginBottom: 20,
32
+ },
33
+ uploadedContainer: {
34
+ flexDirection: 'row',
35
+ alignItems: 'center',
36
+ justifyContent: 'flex-start',
37
+ },
38
+ image: {
39
+ width: 100,
40
+ height: 100,
41
+ borderColor: Colors.dimgray,
42
+ borderWidth: 1,
43
+ },
44
+ imageSpinner: {
45
+ position: 'absolute',
46
+ left: 0,
47
+ right: 0,
48
+ top: 0,
49
+ bottom: 0,
50
+ },
51
+ reUpload: {
52
+ textDecorationLine: 'underline',
53
+ },
54
+ reUploadButtons: {
55
+ marginLeft: 15,
56
+ },
57
+ });
@@ -0,0 +1,75 @@
1
+ import { Ionicons } from '@expo/vector-icons';
2
+ import { TouchableOpacity, View } from 'react-native';
3
+
4
+ import Text from '../Text';
5
+ import style from './style';
6
+
7
+ import type { VirtualKeyboardProps } from '../../configs/types';
8
+
9
+ const keys = [
10
+ {
11
+ key: <Text size="extra-large">1</Text>,
12
+ value: 1,
13
+ },
14
+ {
15
+ key: <Text size="extra-large">2</Text>,
16
+ value: 2,
17
+ },
18
+ {
19
+ key: <Text size="extra-large">3</Text>,
20
+ value: 3,
21
+ },
22
+ {
23
+ key: <Text size="extra-large">4</Text>,
24
+ value: 4,
25
+ },
26
+ {
27
+ key: <Text size="extra-large">5</Text>,
28
+ value: 5,
29
+ },
30
+ {
31
+ key: <Text size="extra-large">6</Text>,
32
+ value: 6,
33
+ },
34
+ {
35
+ key: <Text size="extra-large">7</Text>,
36
+ value: 7,
37
+ },
38
+ {
39
+ key: <Text size="extra-large">8</Text>,
40
+ value: 8,
41
+ },
42
+ {
43
+ key: <Text size="extra-large">9</Text>,
44
+ value: 9,
45
+ },
46
+ {
47
+ key: <Ionicons name="finger-print-outline" style={style.icon} />,
48
+ value: 'biometrics',
49
+ },
50
+ {
51
+ key: <Text size="extra-large">0</Text>,
52
+ value: 0,
53
+ },
54
+ {
55
+ key: <Ionicons name="backspace-outline" style={style.icon} />,
56
+ value: 'back',
57
+ },
58
+ ];
59
+
60
+ const VirtualKeyboard = ({ onPress, hideBiometrics }: VirtualKeyboardProps) => (
61
+ <View style={style.container}>
62
+ {keys.map(({ key, value }) => (
63
+ <TouchableOpacity
64
+ key={`key-${value}`}
65
+ style={style.button}
66
+ onPress={() => onPress(value === 'biometrics' && hideBiometrics ? null : value)}
67
+ disabled={value === 'biometrics' && hideBiometrics}
68
+ >
69
+ {value === 'biometrics' && hideBiometrics ? <Text> </Text> : key}
70
+ </TouchableOpacity>
71
+ ))}
72
+ </View>
73
+ );
74
+
75
+ export default VirtualKeyboard;
@@ -0,0 +1,25 @@
1
+ import { Dimensions, StyleSheet } from 'react-native';
2
+
3
+ import { Colors } from '../../configs/constants';
4
+
5
+ const { width } = Dimensions.get('window');
6
+
7
+ export default StyleSheet.create({
8
+ container: {
9
+ width,
10
+ flexDirection: 'row',
11
+ flexWrap: 'wrap',
12
+ justifyContent: 'center',
13
+ },
14
+ button: {
15
+ width: width / 3.3,
16
+ height: width / 5,
17
+ justifyContent: 'center',
18
+ alignItems: 'center',
19
+ },
20
+ icon: {
21
+ color: Colors.darkblue,
22
+ opacity: 0.6,
23
+ fontSize: 34,
24
+ },
25
+ });
@@ -0,0 +1,29 @@
1
+ export { default as Button } from './Button';
2
+ export { default as Card } from './Card';
3
+ export { default as ConfirmationModal } from './ConfirmationModal';
4
+ export { default as Container } from './Container';
5
+ export { default as CustomChatView } from './CustomChatView';
6
+ export { default as DeckSwiper } from './DeckSwiper';
7
+ export { default as DonutCountdown } from './DonutCountdown';
8
+ export { default as FloatingContainer } from './FloatingContainer';
9
+ export { default as Footer } from './Footer';
10
+ export { default as Header } from './Header';
11
+ export { default as ImagePicker } from './ImagePicker';
12
+ export { default as ImageResponsive } from './ImageResponsive';
13
+ export { default as ImageViewer } from './ImageViewer';
14
+ export { default as Input } from './Input';
15
+ export { default as InputPin } from './InputPin';
16
+ export { default as MenuItem } from './MenuItem';
17
+ export { default as NavigationTitle } from './NavigationTitle';
18
+ export { default as Notification } from './Notification';
19
+ export { default as withPreventDoubleClick } from './PreventDoubleClick';
20
+ export { default as Select } from './Select';
21
+ export { default as SwipeablePanel } from './SwipeablePanel';
22
+ export { default as Switch } from './Switch';
23
+ export { default as TakePicture } from './TakePicture';
24
+ export { default as Text } from './Text';
25
+ export { default as Textarea } from './Textarea';
26
+ export { default as TimeOutButton } from './TimeOutButton';
27
+ export { sendMessage, default as Toast } from './Toast';
28
+ export { default as UploadDocument } from './UploadDocument';
29
+ export { default as VirtualKeyboard } from './VirtualKeyboard';