sapo-components-ui-rn 1.0.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 (215) hide show
  1. package/README.md +69 -0
  2. package/dist/assets/error.png +0 -0
  3. package/dist/assets/icon-checkbox-active.svg +4 -0
  4. package/dist/assets/icon-checkbox.svg +3 -0
  5. package/dist/assets/image_default.png +0 -0
  6. package/dist/assets/images/error.png +0 -0
  7. package/dist/assets/images/image_default.png +0 -0
  8. package/dist/assets/images/info.png +0 -0
  9. package/dist/assets/images/success.png +0 -0
  10. package/dist/assets/images/warning.png +0 -0
  11. package/dist/assets/info.png +0 -0
  12. package/dist/assets/success.png +0 -0
  13. package/dist/assets/svg/icon-checkbox-active.svg +4 -0
  14. package/dist/assets/svg/icon-checkbox.svg +3 -0
  15. package/dist/assets/warning.png +0 -0
  16. package/dist/components/ActivityIndicator.d.ts +28 -0
  17. package/dist/components/Avatar/index.d.ts +17 -0
  18. package/dist/components/Badge/index.d.ts +13 -0
  19. package/dist/components/Button/index.d.ts +23 -0
  20. package/dist/components/ButtonIcon/index.d.ts +18 -0
  21. package/dist/components/Checkbox/index.d.ts +14 -0
  22. package/dist/components/ChipBar/index.d.ts +16 -0
  23. package/dist/components/CountingDot/index.d.ts +13 -0
  24. package/dist/components/FloatingButton/index.d.ts +17 -0
  25. package/dist/components/Icon/index.d.ts +17 -0
  26. package/dist/components/IconSvg/index.d.ts +12 -0
  27. package/dist/components/Image/index.d.ts +14 -0
  28. package/dist/components/ProgressBar.d.ts +42 -0
  29. package/dist/components/RadioButton/index.d.ts +13 -0
  30. package/dist/components/ScaleButton/index.d.ts +4 -0
  31. package/dist/components/SelectionField/index.d.ts +24 -0
  32. package/dist/components/Spacer/index.d.ts +9 -0
  33. package/dist/components/Switch/Switch.d.ts +47 -0
  34. package/dist/components/Switch/utils.d.ts +14 -0
  35. package/dist/components/Text/index.d.ts +14 -0
  36. package/dist/components/TextInput/Addons/Outline.d.ts +15 -0
  37. package/dist/components/TextInput/Addons/Underline.d.ts +19 -0
  38. package/dist/components/TextInput/Adornment/TextInputAdornment.d.ts +43 -0
  39. package/dist/components/TextInput/Adornment/TextInputAffix.d.ts +72 -0
  40. package/dist/components/TextInput/Adornment/enums.d.ts +12 -0
  41. package/dist/components/TextInput/Adornment/types.d.ts +11 -0
  42. package/dist/components/TextInput/Adornment/utils.d.ts +11 -0
  43. package/dist/components/TextInput/Label/InputLabel.d.ts +4 -0
  44. package/dist/components/TextInput/Label/LabelBackground.d.ts +4 -0
  45. package/dist/components/TextInput/TextInput.d.ts +171 -0
  46. package/dist/components/TextInput/TextInputDefault.d.ts +4 -0
  47. package/dist/components/TextInput/TextInputFlat.d.ts +4 -0
  48. package/dist/components/TextInput/constants.d.ts +31 -0
  49. package/dist/components/TextInput/helpers.d.ts +95 -0
  50. package/dist/components/TextInput/types.d.ts +154 -0
  51. package/dist/components/Toast/ToastProvider.d.ts +21 -0
  52. package/dist/components/Toast/index.d.ts +3 -0
  53. package/dist/components/Typography/AnimatedText.d.ts +34 -0
  54. package/dist/components/Typography/StyledText.d.ts +12 -0
  55. package/dist/components/Typography/Text.d.ts +35 -0
  56. package/dist/components/Typography/types.d.ts +2 -0
  57. package/dist/components/View/index.d.ts +38 -0
  58. package/dist/components/ViewVisibleAnimated/index.d.ts +25 -0
  59. package/dist/constants.d.ts +1 -0
  60. package/dist/core/theming.d.ts +43 -0
  61. package/dist/icons/IconArrowDown.d.ts +4 -0
  62. package/dist/icons/IconCheckbox.d.ts +4 -0
  63. package/dist/icons/IconCheckboxActive.d.ts +4 -0
  64. package/dist/icons/IconClearText.d.ts +4 -0
  65. package/dist/icons/IconRadio.d.ts +4 -0
  66. package/dist/icons/IconRadioActive.d.ts +4 -0
  67. package/dist/icons/IconRadioDisable.d.ts +4 -0
  68. package/dist/index.d.ts +33 -0
  69. package/dist/index.esm.js +6758 -0
  70. package/dist/index.esm.js.map +1 -0
  71. package/dist/index.js +6823 -0
  72. package/dist/index.js.map +1 -0
  73. package/dist/styles/fonts.d.ts +78 -0
  74. package/dist/styles/overlay.d.ts +3 -0
  75. package/dist/styles/shadow.d.ts +18 -0
  76. package/dist/styles/themes/DarkTheme.d.ts +2 -0
  77. package/dist/styles/themes/LightTheme.d.ts +2 -0
  78. package/dist/styles/themes/index.d.ts +2 -0
  79. package/dist/styles/themes/tokens.d.ts +830 -0
  80. package/dist/theme/blue.d.ts +14 -0
  81. package/dist/theme/colors.d.ts +99 -0
  82. package/dist/theme/container-styles.d.ts +124 -0
  83. package/dist/theme/dimensions.d.ts +36 -0
  84. package/dist/theme/green.d.ts +15 -0
  85. package/dist/theme/icon.d.ts +5 -0
  86. package/dist/theme/ink.d.ts +11 -0
  87. package/dist/theme/orange.d.ts +14 -0
  88. package/dist/theme/purple.d.ts +6 -0
  89. package/dist/theme/red.d.ts +15 -0
  90. package/dist/theme/themes.d.ts +277 -0
  91. package/dist/theme/white.d.ts +10 -0
  92. package/dist/theme/yellow.d.ts +15 -0
  93. package/dist/types/index.d.ts +65 -0
  94. package/dist/types.d.ts +220 -0
  95. package/dist/utils/BackHandler/BackHandler.d.ts +9 -0
  96. package/dist/utils/BackHandler/BackHandler.native.d.ts +2 -0
  97. package/dist/utils/addEventListener.d.ts +12 -0
  98. package/dist/utils/forwardRef.d.ts +11 -0
  99. package/dist/utils/function-utils.d.ts +12 -0
  100. package/dist/utils/getContrastingColor.d.ts +2 -0
  101. package/dist/utils/hasTouchHandler.d.ts +5 -0
  102. package/dist/utils/roundLayoutSize.d.ts +1 -0
  103. package/dist/utils/splitStyles.d.ts +19 -0
  104. package/dist/utils/toast-manager.d.ts +21 -0
  105. package/dist/utils/useAnimatedValue.d.ts +2 -0
  106. package/dist/utils/useAnimatedValueArray.d.ts +2 -0
  107. package/dist/utils/useIsKeyboardShown.d.ts +6 -0
  108. package/dist/utils/useLayout.d.ts +6 -0
  109. package/dist/utils/useLazyRef.d.ts +2 -0
  110. package/package.json +104 -0
  111. package/src/.DS_Store +0 -0
  112. package/src/assets/images/error.png +0 -0
  113. package/src/assets/images/image_default.png +0 -0
  114. package/src/assets/images/info.png +0 -0
  115. package/src/assets/images/success.png +0 -0
  116. package/src/assets/images/warning.png +0 -0
  117. package/src/assets/svg/icon-checkbox-active.svg +4 -0
  118. package/src/assets/svg/icon-checkbox.svg +3 -0
  119. package/src/babel/.eslintrc +7 -0
  120. package/src/babel/index.js +63 -0
  121. package/src/components/.DS_Store +0 -0
  122. package/src/components/ActivityIndicator.tsx +238 -0
  123. package/src/components/Avatar/index.tsx +102 -0
  124. package/src/components/Badge/index.tsx +55 -0
  125. package/src/components/Button/index.tsx +162 -0
  126. package/src/components/ButtonIcon/index.tsx +98 -0
  127. package/src/components/Checkbox/index.tsx +107 -0
  128. package/src/components/ChipBar/index.tsx +112 -0
  129. package/src/components/CountingDot/index.tsx +63 -0
  130. package/src/components/FloatingButton/index.tsx +99 -0
  131. package/src/components/Icon/index.tsx +135 -0
  132. package/src/components/IconSvg/index.tsx +42 -0
  133. package/src/components/Image/index.tsx +127 -0
  134. package/src/components/ProgressBar.tsx +272 -0
  135. package/src/components/RadioButton/index.tsx +105 -0
  136. package/src/components/ScaleButton/index.tsx +17 -0
  137. package/src/components/SelectionField/index.tsx +166 -0
  138. package/src/components/Spacer/index.tsx +19 -0
  139. package/src/components/Switch/Switch.tsx +110 -0
  140. package/src/components/Switch/utils.ts +96 -0
  141. package/src/components/Text/index.tsx +69 -0
  142. package/src/components/TextInput/.DS_Store +0 -0
  143. package/src/components/TextInput/Addons/Outline.tsx +62 -0
  144. package/src/components/TextInput/Addons/Underline.tsx +71 -0
  145. package/src/components/TextInput/Adornment/TextInputAdornment.tsx +191 -0
  146. package/src/components/TextInput/Adornment/TextInputAffix.tsx +212 -0
  147. package/src/components/TextInput/Adornment/enums.tsx +12 -0
  148. package/src/components/TextInput/Adornment/types.tsx +11 -0
  149. package/src/components/TextInput/Adornment/utils.ts +39 -0
  150. package/src/components/TextInput/Label/InputLabel.tsx +216 -0
  151. package/src/components/TextInput/Label/LabelBackground.tsx +100 -0
  152. package/src/components/TextInput/TextInput.tsx +564 -0
  153. package/src/components/TextInput/TextInputDefault.tsx +187 -0
  154. package/src/components/TextInput/TextInputFlat.tsx +452 -0
  155. package/src/components/TextInput/constants.tsx +48 -0
  156. package/src/components/TextInput/helpers.tsx +546 -0
  157. package/src/components/TextInput/types.tsx +155 -0
  158. package/src/components/Toast/ToastProvider.tsx +69 -0
  159. package/src/components/Toast/index.tsx +239 -0
  160. package/src/components/Typography/AnimatedText.tsx +84 -0
  161. package/src/components/Typography/StyledText.tsx +53 -0
  162. package/src/components/Typography/Text.tsx +189 -0
  163. package/src/components/Typography/types.tsx +5 -0
  164. package/src/components/View/index.tsx +175 -0
  165. package/src/components/ViewVisibleAnimated/index.tsx +199 -0
  166. package/src/constants.tsx +16 -0
  167. package/src/core/theming.tsx +144 -0
  168. package/src/icons/IconArrowDown.tsx +14 -0
  169. package/src/icons/IconCheckbox.tsx +20 -0
  170. package/src/icons/IconCheckboxActive.tsx +18 -0
  171. package/src/icons/IconClearText.tsx +14 -0
  172. package/src/icons/IconRadio.tsx +11 -0
  173. package/src/icons/IconRadioActive.tsx +12 -0
  174. package/src/icons/IconRadioDisable.tsx +12 -0
  175. package/src/index.ts +51 -0
  176. package/src/index.tsx +50 -0
  177. package/src/styles/fonts.tsx +89 -0
  178. package/src/styles/overlay.tsx +69 -0
  179. package/src/styles/shadow.tsx +47 -0
  180. package/src/styles/themes/DarkTheme.tsx +157 -0
  181. package/src/styles/themes/LightTheme.tsx +160 -0
  182. package/src/styles/themes/index.ts +3 -0
  183. package/src/styles/themes/tokens.tsx +481 -0
  184. package/src/theme/blue.ts +25 -0
  185. package/src/theme/colors.ts +21 -0
  186. package/src/theme/container-styles.tsx +126 -0
  187. package/src/theme/dimensions.ts +44 -0
  188. package/src/theme/green.ts +27 -0
  189. package/src/theme/icon.ts +7 -0
  190. package/src/theme/ink.ts +18 -0
  191. package/src/theme/orange.ts +24 -0
  192. package/src/theme/purple.ts +8 -0
  193. package/src/theme/red.ts +26 -0
  194. package/src/theme/themes.tsx +287 -0
  195. package/src/theme/white.ts +16 -0
  196. package/src/theme/yellow.ts +26 -0
  197. package/src/types/index.ts +71 -0
  198. package/src/types/svg.d.ts +5 -0
  199. package/src/types.ts +259 -0
  200. package/src/types.tsx +284 -0
  201. package/src/utils/BackHandler/BackHandler.native.tsx +3 -0
  202. package/src/utils/BackHandler/BackHandler.tsx +11 -0
  203. package/src/utils/addEventListener.tsx +56 -0
  204. package/src/utils/forwardRef.tsx +23 -0
  205. package/src/utils/function-utils.tsx +108 -0
  206. package/src/utils/getContrastingColor.tsx +15 -0
  207. package/src/utils/hasTouchHandler.tsx +23 -0
  208. package/src/utils/roundLayoutSize.ts +2 -0
  209. package/src/utils/splitStyles.ts +60 -0
  210. package/src/utils/toast-manager.tsx +46 -0
  211. package/src/utils/useAnimatedValue.tsx +9 -0
  212. package/src/utils/useAnimatedValueArray.tsx +13 -0
  213. package/src/utils/useIsKeyboardShown.tsx +55 -0
  214. package/src/utils/useLayout.tsx +29 -0
  215. package/src/utils/useLazyRef.tsx +11 -0
@@ -0,0 +1,272 @@
1
+ import * as React from "react";
2
+ import {
3
+ Animated,
4
+ I18nManager,
5
+ LayoutChangeEvent,
6
+ Platform,
7
+ StyleProp,
8
+ StyleSheet,
9
+ View,
10
+ ViewStyle,
11
+ } from "react-native";
12
+
13
+ import setColor from "color";
14
+
15
+ import { useInternalTheme } from "../core/theming";
16
+ import type { ThemeProp } from "../types";
17
+
18
+ export type Props = React.ComponentPropsWithRef<typeof View> & {
19
+ /**
20
+ * Animated value (between 0 and 1). This tells the progress bar to rely on this value to animate it.
21
+ * Note: It should not be used in parallel with the `progress` prop.
22
+ */
23
+ animatedValue?: number;
24
+ /**
25
+ * Progress value (between 0 and 1).
26
+ * Note: It should not be used in parallel with the `animatedValue` prop.
27
+ */
28
+ progress?: number;
29
+ /**
30
+ * Color of the progress bar. The background color will be calculated based on this but you can change it by passing `backgroundColor` to `style` prop.
31
+ */
32
+ color?: string;
33
+ /**
34
+ * If the progress bar will show indeterminate progress.
35
+ */
36
+ indeterminate?: boolean;
37
+ /**
38
+ * Whether to show the ProgressBar (true, the default) or hide it (false).
39
+ */
40
+ visible?: boolean;
41
+ /**
42
+ * Style of filled part of the ProgresBar.
43
+ */
44
+ fillStyle?: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;
45
+ style?: StyleProp<ViewStyle>;
46
+ /**
47
+ * @optional
48
+ */
49
+ theme?: ThemeProp;
50
+ /**
51
+ * testID to be used on tests.
52
+ */
53
+ testID?: string;
54
+ };
55
+
56
+ const INDETERMINATE_DURATION = 2000;
57
+ const INDETERMINATE_MAX_WIDTH = 0.6;
58
+ const { isRTL } = I18nManager;
59
+
60
+ const ProgressBar = ({
61
+ color,
62
+ indeterminate,
63
+ progress = 0,
64
+ visible = true,
65
+ theme: themeOverrides,
66
+ animatedValue,
67
+ style,
68
+ fillStyle,
69
+ testID = "progress-bar",
70
+ ...rest
71
+ }: Props) => {
72
+ const isWeb = Platform.OS === "web";
73
+ const theme = useInternalTheme();
74
+ const { current: timer } = React.useRef<Animated.Value>(
75
+ new Animated.Value(0)
76
+ );
77
+ const { current: fade } = React.useRef<Animated.Value>(new Animated.Value(0));
78
+ const passedAnimatedValue =
79
+ React.useRef<Props["animatedValue"]>(animatedValue);
80
+ const [width, setWidth] = React.useState<number>(0);
81
+ const [prevWidth, setPrevWidth] = React.useState<number>(0);
82
+
83
+ const indeterminateAnimation =
84
+ React.useRef<Animated.CompositeAnimation | null>(null);
85
+
86
+ const { scale } = theme.animation;
87
+
88
+ React.useEffect(() => {
89
+ passedAnimatedValue.current = animatedValue;
90
+ });
91
+
92
+ const startAnimation = React.useCallback(() => {
93
+ // Show progress bar
94
+ Animated.timing(fade, {
95
+ duration: 200 * scale,
96
+ toValue: 1,
97
+ useNativeDriver: true,
98
+ isInteraction: false,
99
+ }).start();
100
+
101
+ /**
102
+ * We shouldn't add @param animatedValue to the
103
+ * deps array, to avoid the unnecessary loop.
104
+ * We can only check if the prop is passed initially,
105
+ * and we do early return.
106
+ */
107
+ const externalAnimation =
108
+ typeof passedAnimatedValue.current !== "undefined" &&
109
+ passedAnimatedValue.current >= 0;
110
+
111
+ if (externalAnimation) {
112
+ return;
113
+ }
114
+
115
+ // Animate progress bar
116
+ if (indeterminate) {
117
+ if (!indeterminateAnimation.current) {
118
+ indeterminateAnimation.current = Animated.timing(timer, {
119
+ duration: INDETERMINATE_DURATION,
120
+ toValue: 1,
121
+ // Animated.loop does not work if useNativeDriver is true on web
122
+ useNativeDriver: !isWeb,
123
+ isInteraction: false,
124
+ });
125
+ }
126
+
127
+ // Reset timer to the beginning
128
+ timer.setValue(0);
129
+
130
+ Animated.loop(indeterminateAnimation.current).start();
131
+ } else {
132
+ Animated.timing(timer, {
133
+ duration: 200 * scale,
134
+ toValue: progress ? progress : 0,
135
+ useNativeDriver: true,
136
+ isInteraction: false,
137
+ }).start();
138
+ }
139
+ }, [fade, scale, indeterminate, timer, progress, isWeb]);
140
+
141
+ const stopAnimation = React.useCallback(() => {
142
+ // Stop indeterminate animation
143
+ if (indeterminateAnimation.current) {
144
+ indeterminateAnimation.current.stop();
145
+ }
146
+
147
+ Animated.timing(fade, {
148
+ duration: 200 * scale,
149
+ toValue: 0,
150
+ useNativeDriver: true,
151
+ isInteraction: false,
152
+ }).start();
153
+ }, [fade, scale]);
154
+
155
+ React.useEffect(() => {
156
+ if (visible) startAnimation();
157
+ else stopAnimation();
158
+ }, [visible, startAnimation, stopAnimation]);
159
+
160
+ React.useEffect(() => {
161
+ if (animatedValue && animatedValue >= 0) {
162
+ timer.setValue(animatedValue);
163
+ }
164
+ }, [animatedValue, timer]);
165
+
166
+ React.useEffect(() => {
167
+ // Start animation the very first time when previously the width was unclear
168
+ if (visible && prevWidth === 0) {
169
+ startAnimation();
170
+ }
171
+ }, [prevWidth, startAnimation, visible]);
172
+
173
+ const onLayout = (event: LayoutChangeEvent) => {
174
+ setPrevWidth(width);
175
+ setWidth(event.nativeEvent.layout.width);
176
+ };
177
+
178
+ const tintColor = color || theme.colors?.surfaceBrandDefault;
179
+ const trackTintColor = theme.colors.surfaceBrandDefault;
180
+
181
+ return (
182
+ <View
183
+ onLayout={onLayout}
184
+ {...rest}
185
+ accessible
186
+ accessibilityRole="progressbar"
187
+ accessibilityState={{ busy: visible }}
188
+ accessibilityValue={
189
+ indeterminate
190
+ ? {}
191
+ : { min: 0, max: 100, now: Math.round(progress * 100) }
192
+ }
193
+ testID={testID}
194
+ >
195
+ <Animated.View
196
+ style={[
197
+ styles.container,
198
+ { backgroundColor: trackTintColor, opacity: fade },
199
+ style,
200
+ ]}
201
+ >
202
+ {width ? (
203
+ <Animated.View
204
+ testID={`${testID}-fill`}
205
+ style={[
206
+ styles.progressBar,
207
+ {
208
+ width,
209
+ backgroundColor: tintColor,
210
+ transform: [
211
+ {
212
+ translateX: timer.interpolate(
213
+ indeterminate
214
+ ? {
215
+ inputRange: [0, 0.5, 1],
216
+ outputRange: [
217
+ (isRTL ? 1 : -1) * 0.5 * width,
218
+ (isRTL ? 1 : -1) *
219
+ 0.5 *
220
+ INDETERMINATE_MAX_WIDTH *
221
+ width,
222
+ (isRTL ? -1 : 1) * 0.7 * width,
223
+ ],
224
+ }
225
+ : {
226
+ inputRange: [0, 1],
227
+ outputRange: [(isRTL ? 1 : -1) * 0.5 * width, 0],
228
+ }
229
+ ),
230
+ },
231
+ {
232
+ // Workaround for workaround for https://github.com/facebook/react-native/issues/6278
233
+ scaleX: timer.interpolate(
234
+ indeterminate
235
+ ? {
236
+ inputRange: [0, 0.5, 1],
237
+ outputRange: [
238
+ 0.0001,
239
+ INDETERMINATE_MAX_WIDTH,
240
+ 0.0001,
241
+ ],
242
+ }
243
+ : {
244
+ inputRange: [0, 1],
245
+ outputRange: [0.0001, 1],
246
+ }
247
+ ),
248
+ },
249
+ ],
250
+ },
251
+ fillStyle,
252
+ ]}
253
+ />
254
+ ) : null}
255
+ </Animated.View>
256
+ </View>
257
+ );
258
+ };
259
+
260
+ const styles = StyleSheet.create({
261
+ container: {
262
+ height: 4,
263
+ overflow: "hidden",
264
+ borderRadius: 10,
265
+ },
266
+
267
+ progressBar: {
268
+ flex: 1,
269
+ },
270
+ });
271
+
272
+ export default ProgressBar;
@@ -0,0 +1,105 @@
1
+ import React, { useState, useCallback, useMemo, useEffect } from "react";
2
+ import { StyleProp, ViewStyle, StyleSheet, TextStyle } from "react-native";
3
+ import View from "../View";
4
+ import { CONSTANTS } from "../../styles/themes/tokens";
5
+ import Text from "../Text";
6
+ import { useInternalTheme } from "../../core/theming";
7
+ import containerStyles from "../../theme/container-styles";
8
+ import Icon from "../Icon";
9
+
10
+ interface RadioButtonProps {
11
+ style?: StyleProp<ViewStyle>;
12
+ content: string;
13
+ onPress?: (val?: any) => void;
14
+ textStyle?: StyleProp<TextStyle>;
15
+ disabled?: boolean;
16
+ leftIcon?: React.ReactNode;
17
+ checked?: boolean;
18
+ }
19
+
20
+ const RadioButton = ({
21
+ style,
22
+ content = "content",
23
+ textStyle,
24
+ onPress,
25
+ disabled = false,
26
+ leftIcon,
27
+ checked = false,
28
+ }: RadioButtonProps) => {
29
+ const theme = useInternalTheme();
30
+ const { colors } = theme;
31
+ const [isActive, setActive] = useState<boolean>(checked);
32
+
33
+ const handlePressChipBar = useCallback(() => {
34
+ setActive(!isActive);
35
+ onPress?.();
36
+ }, [isActive]);
37
+
38
+ useEffect(() => {
39
+ setActive(checked);
40
+ }, [checked]);
41
+
42
+ const getColorCheckbox = useMemo(() => {
43
+ if (disabled) {
44
+ return colors.iconPrimaryDisabled;
45
+ }
46
+ if (isActive) {
47
+ return colors.iconBrandDefault;
48
+ }
49
+ return colors.surfacePrimaryDefault;
50
+ }, [isActive, disabled]);
51
+
52
+ return (
53
+ <View
54
+ row
55
+ disabled={disabled}
56
+ alignCenter
57
+ style={[style]}
58
+ onPress={handlePressChipBar}
59
+ >
60
+ {leftIcon ? (
61
+ <View paddingRight={CONSTANTS.SPACE_8}>{leftIcon}</View>
62
+ ) : (
63
+ <View paddingRight={CONSTANTS.SPACE_8}>
64
+ <Icon
65
+ name={
66
+ disabled
67
+ ? "IconRadioDisable"
68
+ : isActive
69
+ ? "IconRadioActive"
70
+ : "IconRadio"
71
+ }
72
+ type="Svg"
73
+ size={24}
74
+ color={getColorCheckbox}
75
+ />
76
+ </View>
77
+ )}
78
+
79
+ <View>
80
+ <Text
81
+ color={colors.textDefault}
82
+ style={[
83
+ styles.text14,
84
+ disabled && {
85
+ color: colors.textSecondary,
86
+ },
87
+ textStyle,
88
+ ]}
89
+ >
90
+ {content}
91
+ </Text>
92
+ </View>
93
+ </View>
94
+ );
95
+ };
96
+
97
+ const styles = StyleSheet.create({
98
+ ...containerStyles,
99
+ icon: {
100
+ width: 24,
101
+ height: 24,
102
+ },
103
+ });
104
+
105
+ export default RadioButton;
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { TouchableOpacity, TouchableOpacityProps } from "react-native";
3
+
4
+ const ScaleButton = ({
5
+ children,
6
+ style,
7
+ onPress = () => {},
8
+ ...rest
9
+ }: TouchableOpacityProps) => {
10
+ return (
11
+ <TouchableOpacity {...rest} onPress={onPress}>
12
+ {children}
13
+ </TouchableOpacity>
14
+ );
15
+ };
16
+
17
+ export default React.memo(ScaleButton);
@@ -0,0 +1,166 @@
1
+ //
2
+ // Created by Dung Nguyen on 08/01/25.
3
+ //
4
+ import React from "react";
5
+ import {
6
+ StyleSheet,
7
+ StyleProp,
8
+ ViewStyle,
9
+ TouchableOpacityProps,
10
+ TextStyle,
11
+ } from "react-native";
12
+
13
+ import { CONSTANTS } from "../../styles/themes/tokens";
14
+ import ScaleButton from "../ScaleButton";
15
+ import Text, { IText } from "../Text";
16
+ import View from "../View";
17
+ import { useInternalTheme } from "../../core/theming";
18
+ import { ThemeProp } from "../../types";
19
+ import Spacer from "../Spacer";
20
+ import Icon from "../Icon";
21
+ import containerStyles from "../../theme/container-styles";
22
+
23
+ export interface SelectionFieldProps extends TouchableOpacityProps {
24
+ style?: StyleProp<ViewStyle>;
25
+ borderColor?: string;
26
+ content?: string;
27
+ label?: string;
28
+ error?: string;
29
+ left?: React.ReactNode;
30
+ right?: React.ReactNode;
31
+ textProps?: IText;
32
+ textColor?: string;
33
+ labelColor?: string;
34
+ size?: number;
35
+ textStyle?: TextStyle;
36
+ labelStyle?: TextStyle;
37
+ disabled?: boolean;
38
+ onPress?: (res?: any) => void;
39
+ theme?: ThemeProp;
40
+ }
41
+ const SelectionField = ({
42
+ style,
43
+ content = "content",
44
+ label = "",
45
+ error = "",
46
+ borderColor,
47
+ left,
48
+ right,
49
+ textStyle,
50
+ labelStyle,
51
+ textProps,
52
+ onPress,
53
+ disabled = false,
54
+ textColor,
55
+ labelColor,
56
+ size = 16,
57
+ theme: themeOverrides,
58
+ ...props
59
+ }: SelectionFieldProps) => {
60
+ const theme = useInternalTheme();
61
+ const { colors } = theme;
62
+
63
+ const disabledTextStyle = {
64
+ color: colors.textSecondary,
65
+ };
66
+
67
+ return (
68
+ <View>
69
+ <ScaleButton
70
+ activeOpacity={0.8}
71
+ onPress={onPress}
72
+ {...props}
73
+ disabled={disabled || false}
74
+ >
75
+ <View
76
+ style={[
77
+ styles.container,
78
+ {
79
+ borderRadius: CONSTANTS.BORDER_RADIUS_6,
80
+ },
81
+
82
+ [styles.border, { borderColor: colors.borderBrandDefault }],
83
+ borderColor && { borderColor: borderColor },
84
+ disabled && [
85
+ styles.disabled,
86
+ {
87
+ borderColor: colors.borderPrimaryDisabled,
88
+ backgroundColor: colors.surfacePrimaryDisabled,
89
+ },
90
+ ],
91
+ error.length > 0 && [
92
+ {
93
+ borderColor: colors.borderErrorDefault,
94
+ backgroundColor: colors.surfacePrimaryDefault,
95
+ },
96
+ ],
97
+ style,
98
+ ]}
99
+ >
100
+ <Spacer width={CONSTANTS.SPACE_12} />
101
+
102
+ <View full>
103
+ {label.toString() !== "" && (
104
+ <Text
105
+ color={labelColor || colors.textSecondary}
106
+ style={[
107
+ styles.text12,
108
+ disabled && {
109
+ color: colors.textPlaceholder,
110
+ },
111
+ error.length > 0 && {
112
+ color: colors.textErrorDefault,
113
+ },
114
+ ]}
115
+ >
116
+ {label}
117
+ </Text>
118
+ )}
119
+ <Text
120
+ numberOfLines={1}
121
+ color={textColor || colors.textDefault}
122
+ size={size}
123
+ style={[disabled && disabledTextStyle, textStyle]}
124
+ {...textProps}
125
+ >
126
+ {content}
127
+ </Text>
128
+ </View>
129
+
130
+ {right || <Icon name={"IconArrowDown"} type="Svg" size={24} />}
131
+ <Spacer width={CONSTANTS.SPACE_12} />
132
+ </View>
133
+ </ScaleButton>
134
+ {error.length > 0 && (
135
+ <View
136
+ paddingHorizontal={CONSTANTS.SPACE_12}
137
+ paddingVertical={CONSTANTS.SPACE_4}
138
+ >
139
+ <Text style={styles.text12} color={colors.textErrorDefault}>
140
+ {error}
141
+ </Text>
142
+ </View>
143
+ )}
144
+ </View>
145
+ );
146
+ };
147
+
148
+ const styles = StyleSheet.create({
149
+ ...containerStyles,
150
+ disabled: { opacity: 0.6 },
151
+ container: {
152
+ minHeight: CONSTANTS.BUTTON_HEIGHT,
153
+ flexDirection: "row",
154
+ alignItems: "center",
155
+ justifyContent: "space-between",
156
+ paddingVertical: CONSTANTS.SPACE_6,
157
+ },
158
+ border: {
159
+ borderWidth: CONSTANTS.BORDER_WIDTH_1,
160
+ },
161
+ small: {
162
+ height: CONSTANTS.BUTTON_HEIGHT_SMALL,
163
+ },
164
+ });
165
+
166
+ export default React.memo(SelectionField);
@@ -0,0 +1,19 @@
1
+ import React from "react";
2
+ import View from "../View";
3
+ import { CONSTANTS } from "../../styles/themes/tokens";
4
+ import { StyleProp, ViewStyle } from "react-native";
5
+ interface SpacerProps {
6
+ width?: number;
7
+ height?: number;
8
+ style?: StyleProp<ViewStyle>;
9
+ }
10
+
11
+ const Spacer = ({
12
+ style,
13
+ width = CONSTANTS.SPACE_16,
14
+ height = CONSTANTS.SPACE_12,
15
+ }: SpacerProps) => {
16
+ return <View width={width} height={height} style={[style]} />;
17
+ };
18
+
19
+ export default Spacer;
@@ -0,0 +1,110 @@
1
+ import * as React from "react";
2
+ import {
3
+ NativeModules,
4
+ Platform,
5
+ StyleProp,
6
+ Switch as NativeSwitch,
7
+ ViewStyle,
8
+ } from "react-native";
9
+ import View from "../View";
10
+ import { getSwitchColor } from "./utils";
11
+ import { useInternalTheme } from "../../core/theming";
12
+ import type { ThemeProp } from "../../types";
13
+
14
+ const version = NativeModules.PlatformConstants
15
+ ? NativeModules.PlatformConstants.reactNativeVersion
16
+ : undefined;
17
+
18
+ export type Props = React.ComponentPropsWithRef<typeof NativeSwitch> & {
19
+ /**
20
+ * Disable toggling the switch.
21
+ */
22
+ disabled?: boolean;
23
+ /**
24
+ * Value of the switch, true means 'on', false means 'off'.
25
+ */
26
+ value?: boolean;
27
+ /**
28
+ * Custom color for switch.
29
+ */
30
+ color?: string;
31
+ /**
32
+ * Callback called with the new value when it changes.
33
+ */
34
+ onValueChange?: Function;
35
+ style?: StyleProp<ViewStyle>;
36
+ /**
37
+ * @optional
38
+ */
39
+ theme?: ThemeProp;
40
+ };
41
+
42
+ /**
43
+ * Switch is a visual toggle between two mutually exclusive states — on and off.
44
+ *
45
+ * ## Usage
46
+ * ```js
47
+ * import * as React from 'react';
48
+ * import { Switch } from 'react-native-paper';
49
+ *
50
+ * const MyComponent = () => {
51
+ * const [isSwitchOn, setIsSwitchOn] = React.useState(false);
52
+ *
53
+ * const onToggleSwitch = () => setIsSwitchOn(!isSwitchOn);
54
+ *
55
+ * return <Switch value={isSwitchOn} onValueChange={onToggleSwitch} />;
56
+ * };
57
+ *
58
+ * export default MyComponent;
59
+ * ```
60
+ */
61
+ const Switch = ({
62
+ value,
63
+ disabled,
64
+ onValueChange,
65
+ color,
66
+ theme: themeOverrides,
67
+ ...rest
68
+ }: Props) => {
69
+ const theme = useInternalTheme();
70
+ const { checkedColor, onTintColor, thumbTintColor } = getSwitchColor({
71
+ theme,
72
+ disabled,
73
+ value,
74
+ color,
75
+ });
76
+
77
+ const props =
78
+ version && version.major === 0 && version.minor <= 56
79
+ ? {
80
+ onTintColor,
81
+ thumbTintColor,
82
+ }
83
+ : Platform.OS === "web"
84
+ ? {
85
+ activeTrackColor: onTintColor,
86
+ thumbColor: thumbTintColor,
87
+ activeThumbColor: checkedColor,
88
+ }
89
+ : {
90
+ thumbColor: thumbTintColor,
91
+ trackColor: {
92
+ true: onTintColor,
93
+ false: onTintColor,
94
+ },
95
+ };
96
+
97
+ return (
98
+ <View row>
99
+ <NativeSwitch
100
+ value={value}
101
+ disabled={disabled}
102
+ onValueChange={disabled ? undefined : onValueChange}
103
+ {...props}
104
+ {...rest}
105
+ />
106
+ </View>
107
+ );
108
+ };
109
+
110
+ export default Switch;