@retray-dev/ui-kit 5.2.0 → 6.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 (42) hide show
  1. package/COMPONENTS.md +500 -140
  2. package/EXAMPLES.md +666 -0
  3. package/README.md +3 -3
  4. package/dist/index.d.mts +253 -49
  5. package/dist/index.d.ts +253 -49
  6. package/dist/index.js +955 -610
  7. package/dist/index.mjs +886 -552
  8. package/package.json +9 -3
  9. package/src/components/Accordion/Accordion.tsx +31 -4
  10. package/src/components/AlertBanner/AlertBanner.tsx +16 -33
  11. package/src/components/Avatar/Avatar.tsx +21 -7
  12. package/src/components/Button/Button.tsx +34 -13
  13. package/src/components/ButtonGroup/ButtonGroup.tsx +60 -0
  14. package/src/components/ButtonGroup/index.ts +1 -0
  15. package/src/components/Card/Card.tsx +12 -9
  16. package/src/components/Chip/Chip.tsx +8 -1
  17. package/src/components/ConfirmDialog/ConfirmDialog.tsx +4 -4
  18. package/src/components/CurrencyDisplay/CurrencyDisplay.tsx +38 -5
  19. package/src/components/DetailRow/DetailRow.tsx +140 -0
  20. package/src/components/DetailRow/index.ts +1 -0
  21. package/src/components/EmptyState/EmptyState.tsx +21 -6
  22. package/src/components/Input/Input.tsx +21 -10
  23. package/src/components/LabelValue/LabelValue.tsx +25 -4
  24. package/src/components/ListItem/ListItem.tsx +14 -8
  25. package/src/components/MediaCard/MediaCard.tsx +1 -0
  26. package/src/components/MenuItem/MenuItem.tsx +206 -0
  27. package/src/components/MenuItem/index.ts +2 -0
  28. package/src/components/MonthPicker/MonthPicker.tsx +18 -6
  29. package/src/components/Select/Select.tsx +1 -1
  30. package/src/components/Separator/Separator.tsx +2 -0
  31. package/src/components/Sheet/Sheet.tsx +165 -36
  32. package/src/components/Sheet/index.ts +1 -1
  33. package/src/components/Tabs/Tabs.tsx +4 -4
  34. package/src/components/Textarea/Textarea.tsx +66 -29
  35. package/src/components/Toast/Toast.tsx +41 -267
  36. package/src/components/Toast/index.ts +1 -2
  37. package/src/components/Toggle/Toggle.tsx +2 -2
  38. package/src/index.ts +6 -0
  39. package/src/theme/colors.ts +3 -0
  40. package/src/theme/types.ts +11 -0
  41. package/src/tokens.ts +4 -4
  42. package/src/utils/typography.ts +24 -0
@@ -5,10 +5,12 @@ import { selectionAsync as hapticSelection } from '../../utils/haptics'
5
5
  import { useTheme } from '../../theme'
6
6
  import { s, vs, ms, mvs } from '../../utils/scaling'
7
7
 
8
- const MONTH_NAMES = [
9
- 'January', 'February', 'March', 'April', 'May', 'June',
10
- 'July', 'August', 'September', 'October', 'November', 'December',
11
- ]
8
+ const MONTH_NAMES: Record<string, string[]> = {
9
+ en: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
10
+ es: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
11
+ pt: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
12
+ fr: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'],
13
+ }
12
14
 
13
15
  export interface MonthPickerValue {
14
16
  /** Month number 1–12 */
@@ -19,12 +21,22 @@ export interface MonthPickerValue {
19
21
  export interface MonthPickerProps {
20
22
  value: MonthPickerValue
21
23
  onChange: (value: MonthPickerValue) => void
24
+ /** BCP 47 locale tag. Built-in: 'en' | 'es' | 'pt' | 'fr'. For other locales supply formatLabel. */
25
+ locale?: string
26
+ /** Custom label formatter. Takes precedence over locale. */
27
+ formatLabel?: (value: MonthPickerValue) => string
22
28
  style?: ViewStyle
23
29
  }
24
30
 
25
- export function MonthPicker({ value, onChange, style }: MonthPickerProps) {
31
+ export function MonthPicker({ value, onChange, locale = 'en', formatLabel, style }: MonthPickerProps) {
26
32
  const { colors } = useTheme()
27
33
 
34
+ const getLabel = (): string => {
35
+ if (formatLabel) return formatLabel(value)
36
+ const names = MONTH_NAMES[locale] ?? MONTH_NAMES.en
37
+ return `${names[value.month - 1]} ${value.year}`
38
+ }
39
+
28
40
  const handlePrev = () => {
29
41
  hapticSelection()
30
42
  if (value.month === 1) {
@@ -54,7 +66,7 @@ export function MonthPicker({ value, onChange, style }: MonthPickerProps) {
54
66
  <Entypo name="chevron-left" size={22} color={colors.foreground} />
55
67
  </TouchableOpacity>
56
68
  <Text style={[styles.label, { color: colors.foreground }]} allowFontScaling={true}>
57
- {MONTH_NAMES[value.month - 1]} {value.year}
69
+ {getLabel()}
58
70
  </Text>
59
71
  <TouchableOpacity
60
72
  style={styles.arrow}
@@ -109,7 +109,7 @@ export function Select({
109
109
  >
110
110
  {selected?.label ?? placeholder}
111
111
  </Text>
112
- <Entypo name="chevron-with-circle-down" size={20} color={colors.foregroundMuted} />
112
+ <Entypo name="chevron-down" size={20} color={colors.foregroundMuted} />
113
113
  </TouchableOpacity>
114
114
  </Animated.View>
115
115
  ) : null}
@@ -25,9 +25,11 @@ const styles = StyleSheet.create({
25
25
  horizontal: {
26
26
  height: 1,
27
27
  width: '100%',
28
+ opacity: 0.7,
28
29
  },
29
30
  vertical: {
30
31
  width: 1,
31
32
  height: '100%',
33
+ opacity: 0.7,
32
34
  },
33
35
  })
@@ -1,102 +1,214 @@
1
- import React, { useEffect, useRef } from 'react'
2
- import { View, Text, StyleSheet, ViewStyle } from 'react-native'
1
+ import React, { useCallback, useEffect, useRef } from 'react'
2
+ import { View, Text, TouchableOpacity, StyleSheet, ViewStyle, Dimensions, Platform } from 'react-native'
3
3
  import {
4
4
  BottomSheetModal,
5
5
  BottomSheetView,
6
6
  BottomSheetScrollView,
7
7
  BottomSheetBackdrop,
8
8
  BottomSheetModalProvider,
9
+ BottomSheetTextInput,
10
+ BottomSheetFooter,
9
11
  type BottomSheetBackdropProps,
12
+ type BottomSheetFooterProps,
10
13
  } from '@gorhom/bottom-sheet'
11
- import { impactLight } from '../../utils/haptics'
14
+ import { useSafeAreaInsets } from 'react-native-safe-area-context'
15
+ import { AntDesign } from '@expo/vector-icons'
16
+ import { impactMedium } from '../../utils/haptics'
12
17
  import { useTheme } from '../../theme'
13
18
  import { s, vs, ms, mvs } from '../../utils/scaling'
14
19
 
20
+ const SCREEN_HEIGHT = Dimensions.get('window').height
21
+ const DEFAULT_MAX_HEIGHT = SCREEN_HEIGHT * 0.85
22
+ const isAndroid = Platform.OS === 'android'
23
+
15
24
  export { BottomSheetModalProvider }
25
+ // Re-export BottomSheetTextInput as SheetTextInput for consumer convenience
26
+ export { BottomSheetTextInput as SheetTextInput }
16
27
 
17
28
  export interface SheetProps {
18
29
  open: boolean
19
30
  onClose: () => void
20
31
  title?: string
32
+ /** Secondary text below title. */
33
+ subtitle?: string
34
+ /** @deprecated Use `subtitle` instead. */
21
35
  description?: string
36
+ /** Show an X close button in the header. */
37
+ showCloseButton?: boolean
22
38
  children?: React.ReactNode
23
39
  /** Style for the inner content container. */
24
40
  style?: ViewStyle
25
- /** Render children inside BottomSheetScrollView so gestures are handled correctly on both platforms. */
41
+ /** Style for the content wrapper (outside the scroll container). */
42
+ contentStyle?: ViewStyle
43
+ /** Render children inside BottomSheetScrollView. */
26
44
  scrollable?: boolean
27
45
  /** Cap sheet height (dp). Children scroll when content exceeds this value. */
28
46
  maxHeight?: number
47
+ /**
48
+ * Keyboard behavior — how the sheet responds to keyboard appearance.
49
+ * - 'interactive': offset sheet by keyboard size (default, works on both platforms)
50
+ * - 'fillParent': extend sheet to fill parent view (can cause restore issues with dynamic sizing)
51
+ * - 'extend': extend sheet to maximum snap point
52
+ *
53
+ * Default: 'interactive' on both platforms.
54
+ */
55
+ keyboardBehavior?: 'extend' | 'fillParent' | 'interactive'
56
+ /**
57
+ * Keyboard blur behavior — what happens when keyboard dismisses.
58
+ * - 'none': do nothing
59
+ * - 'restore': restore sheet to previous position (default)
60
+ */
61
+ keyboardBlurBehavior?: 'none' | 'restore'
62
+ /**
63
+ * Blur keyboard when user starts dragging the sheet down.
64
+ * Default: true (recommended for better UX)
65
+ */
66
+ enableBlurKeyboardOnGesture?: boolean
67
+ /**
68
+ * Android-only: defines keyboard input mode.
69
+ * - 'adjustPan': pan the sheet content (default, fixes restore issues with dynamic sizing)
70
+ * - 'adjustResize': resize the sheet container (can cause transparent gap on dismiss)
71
+ */
72
+ android_keyboardInputMode?: 'adjustPan' | 'adjustResize'
73
+ /** Sticky footer rendered below the scroll area. */
74
+ footer?: React.ReactNode
75
+ /**
76
+ * Array of snap points for the sheet (e.g., ['50%', '85%'] or [200, 500]).
77
+ * When provided, disables enableDynamicSizing.
78
+ * When omitted, sheet uses dynamic sizing (auto-fits content).
79
+ */
80
+ snapPoints?: (string | number)[]
29
81
  }
30
82
 
31
83
  export function Sheet({
32
84
  open,
33
85
  onClose,
34
86
  title,
87
+ subtitle,
35
88
  description,
89
+ showCloseButton = false,
36
90
  children,
37
91
  style,
92
+ contentStyle,
38
93
  scrollable,
39
94
  maxHeight,
95
+ keyboardBehavior,
96
+ keyboardBlurBehavior = 'restore',
97
+ enableBlurKeyboardOnGesture = true,
98
+ android_keyboardInputMode = 'adjustPan',
99
+ footer,
100
+ snapPoints,
40
101
  }: SheetProps) {
41
102
  const { colors } = useTheme()
103
+ const insets = useSafeAreaInsets()
42
104
  const ref = useRef<BottomSheetModal>(null)
105
+
106
+ // 'interactive' + 'adjustPan' works properly with enableDynamicSizing on both platforms
107
+ // 'fillParent' + 'adjustResize' causes restore issues (transparent gap when keyboard dismisses)
108
+ const effectiveKeyboardBehavior = keyboardBehavior ?? 'interactive'
43
109
 
44
110
  useEffect(() => {
45
111
  if (open) {
46
- impactLight()
112
+ impactMedium()
47
113
  ref.current?.present()
48
114
  } else {
49
115
  ref.current?.dismiss()
50
116
  }
51
117
  }, [open])
52
118
 
53
- const renderBackdrop = (props: BottomSheetBackdropProps) => (
119
+ const renderBackdrop = useCallback((props: BottomSheetBackdropProps) => (
54
120
  <BottomSheetBackdrop
55
121
  {...props}
56
122
  disappearsOnIndex={-1}
57
123
  appearsOnIndex={0}
58
124
  pressBehavior="close"
59
125
  />
60
- )
126
+ ), [])
127
+
128
+ const renderFooter = useCallback((props: BottomSheetFooterProps) => {
129
+ if (!footer) return null
130
+ return (
131
+ <BottomSheetFooter {...props}>
132
+ {footer}
133
+ </BottomSheetFooter>
134
+ )
135
+ }, [footer])
136
+
137
+ const effectiveSubtitle = subtitle ?? description
138
+
139
+ const showHeader = !!(title || effectiveSubtitle || showCloseButton)
61
140
 
62
- const headerNode = (title || description) ? (
141
+ const headerNode = showHeader ? (
63
142
  <View style={styles.header}>
64
- {title ? (
65
- <Text style={[styles.title, { color: colors.foreground }]} allowFontScaling={true}>{title}</Text>
66
- ) : null}
67
- {description ? (
68
- <Text style={[styles.description, { color: colors.foregroundMuted }]} allowFontScaling={true}>
69
- {description}
143
+ <View style={styles.headerRow}>
144
+ {title ? (
145
+ <Text style={[styles.title, { color: colors.foreground }]} allowFontScaling={true}>
146
+ {title}
147
+ </Text>
148
+ ) : <View style={{ flex: 1 }} />}
149
+ {showCloseButton ? (
150
+ <TouchableOpacity
151
+ onPress={onClose}
152
+ style={styles.closeButton}
153
+ activeOpacity={0.6}
154
+ touchSoundDisabled={true}
155
+ >
156
+ <AntDesign name="close" size={ms(18)} color={colors.foregroundMuted} />
157
+ </TouchableOpacity>
158
+ ) : null}
159
+ </View>
160
+ {effectiveSubtitle ? (
161
+ <Text style={[styles.subtitle, { color: colors.foregroundMuted }]} allowFontScaling={true}>
162
+ {effectiveSubtitle}
70
163
  </Text>
71
164
  ) : null}
72
165
  </View>
73
166
  ) : null
74
167
 
75
168
  const useScroll = scrollable || !!maxHeight
76
-
169
+ const effectiveMaxHeight = maxHeight ?? DEFAULT_MAX_HEIGHT
170
+
171
+ // If snapPoints provided, disable dynamic sizing. Otherwise use dynamic sizing.
172
+ const useDynamicSizing = !snapPoints
173
+
77
174
  return (
78
175
  <BottomSheetModal
79
176
  ref={ref}
80
- enableDynamicSizing
177
+ enableDynamicSizing={useDynamicSizing}
178
+ snapPoints={snapPoints}
179
+ maxDynamicContentSize={useDynamicSizing ? effectiveMaxHeight : undefined}
81
180
  onDismiss={onClose}
82
181
  backdropComponent={renderBackdrop}
182
+ footerComponent={footer ? renderFooter : undefined}
83
183
  backgroundStyle={[styles.background, { backgroundColor: colors.card }]}
84
184
  handleIndicatorStyle={[styles.handle, { backgroundColor: colors.border }]}
85
185
  enablePanDownToClose
186
+ topInset={insets.top}
187
+ keyboardBehavior={effectiveKeyboardBehavior}
188
+ keyboardBlurBehavior={keyboardBlurBehavior}
189
+ android_keyboardInputMode={android_keyboardInputMode}
190
+ enableBlurKeyboardOnGesture={enableBlurKeyboardOnGesture}
86
191
  >
87
- <BottomSheetView style={maxHeight ? { maxHeight } : undefined}>
88
- {useScroll ? (
89
- <BottomSheetScrollView contentContainerStyle={[styles.content, style]}>
90
- {headerNode}
91
- {children}
92
- </BottomSheetScrollView>
93
- ) : (
94
- <BottomSheetView style={[styles.content, style]}>
95
- {headerNode}
96
- {children}
97
- </BottomSheetView>
98
- )}
99
- </BottomSheetView>
192
+ {useScroll ? (
193
+ <BottomSheetScrollView
194
+ contentContainerStyle={[
195
+ styles.scrollContent,
196
+ style,
197
+ ]}
198
+ style={contentStyle}
199
+ showsVerticalScrollIndicator={true}
200
+ indicatorStyle="black"
201
+ persistentScrollbar={isAndroid}
202
+ >
203
+ {headerNode}
204
+ {children}
205
+ </BottomSheetScrollView>
206
+ ) : (
207
+ <BottomSheetView style={[styles.content, contentStyle, style]}>
208
+ {headerNode}
209
+ {children}
210
+ </BottomSheetView>
211
+ )}
100
212
  </BottomSheetModal>
101
213
  )
102
214
  }
@@ -111,21 +223,38 @@ const styles = StyleSheet.create({
111
223
  height: vs(4),
112
224
  borderRadius: ms(2),
113
225
  },
114
- content: {
115
- paddingHorizontal: s(24),
116
- paddingBottom: vs(32),
117
- },
118
226
  header: {
119
- gap: vs(8),
120
- marginBottom: vs(16),
227
+ paddingHorizontal: s(16),
228
+ paddingTop: vs(4),
229
+ paddingBottom: vs(12),
230
+ gap: vs(4),
231
+ },
232
+ headerRow: {
233
+ flexDirection: 'row',
234
+ alignItems: 'center',
235
+ justifyContent: 'space-between',
121
236
  },
122
237
  title: {
123
238
  fontFamily: 'Poppins-SemiBold',
124
239
  fontSize: ms(18),
240
+ flex: 1,
125
241
  },
126
- description: {
242
+ subtitle: {
127
243
  fontFamily: 'Poppins-Regular',
128
244
  fontSize: ms(14),
129
245
  lineHeight: mvs(20),
130
246
  },
247
+ closeButton: {
248
+ padding: s(4),
249
+ marginLeft: s(8),
250
+ },
251
+ content: {
252
+ paddingHorizontal: s(16),
253
+ paddingBottom: vs(32),
254
+ },
255
+ scrollContent: {
256
+ paddingHorizontal: s(16),
257
+ paddingBottom: vs(32),
258
+ paddingRight: s(16),
259
+ },
131
260
  })
@@ -1,2 +1,2 @@
1
- export { Sheet, BottomSheetModalProvider } from './Sheet'
1
+ export { Sheet, BottomSheetModalProvider, SheetTextInput } from './Sheet'
2
2
  export type { SheetProps } from './Sheet'
@@ -49,11 +49,11 @@ function TabTrigger({
49
49
  const scale = useRef(new Animated.Value(1)).current
50
50
 
51
51
  const handlePressIn = () => {
52
- Animated.spring(scale, { toValue: 0.95, useNativeDriver: nativeDriver, speed: 40, bounciness: 0 }).start()
52
+ Animated.spring(scale, { toValue: 0.95, useNativeDriver: nativeDriver, stiffness: 600, damping: 35, mass: 0.8 }).start()
53
53
  }
54
54
 
55
55
  const handlePressOut = () => {
56
- Animated.spring(scale, { toValue: 1, useNativeDriver: nativeDriver, speed: 40, bounciness: 4 }).start()
56
+ Animated.spring(scale, { toValue: 1, useNativeDriver: nativeDriver, stiffness: 280, damping: 22, mass: 0.8 }).start()
57
57
  }
58
58
 
59
59
  const isUnderline = variant === 'underline'
@@ -108,8 +108,8 @@ export function Tabs({ tabs, variant = 'pill', value, onValueChange, children, s
108
108
  if (!layout) return
109
109
  if (animate) {
110
110
  Animated.parallel([
111
- Animated.spring(pillX, { toValue: layout.x, useNativeDriver: false, speed: 20, bounciness: 0 }),
112
- Animated.spring(pillWidth, { toValue: layout.width, useNativeDriver: false, speed: 20, bounciness: 0 }),
111
+ Animated.spring(pillX, { toValue: layout.x, useNativeDriver: false, stiffness: 380, damping: 38, mass: 1.0 }),
112
+ Animated.spring(pillWidth, { toValue: layout.width, useNativeDriver: false, stiffness: 380, damping: 38, mass: 1.0 }),
113
113
  ]).start()
114
114
  } else {
115
115
  pillX.setValue(layout.x)
@@ -2,6 +2,7 @@ import React, { useState } from 'react'
2
2
  import { TextInput, View, Text, StyleSheet, TextInputProps, ViewStyle, Platform } from 'react-native'
3
3
  import { useTheme } from '../../theme'
4
4
  import { s, vs, ms } from '../../utils/scaling'
5
+ import { renderIcon } from '../../utils/icons'
5
6
 
6
7
  const webInputResetStyle: any =
7
8
  Platform.OS === 'web'
@@ -16,6 +17,12 @@ export interface TextareaProps extends TextInputProps {
16
17
  hint?: string
17
18
  /** Number of visible text rows. Defaults to `4`. Controls `numberOfLines` and `minHeight`. */
18
19
  rows?: number
20
+ /** Icon name from @expo/vector-icons rendered inside top-left corner. */
21
+ prefixIcon?: string
22
+ /** Custom icon node rendered top-left. */
23
+ prefixIconNode?: React.ReactNode
24
+ /** Override prefix icon color. Defaults to foregroundMuted. */
25
+ prefixIconColor?: string
19
26
  /** Style for the outer container `View`. Use `style` (from `TextInputProps`) to style the `TextInput` itself. */
20
27
  containerStyle?: ViewStyle
21
28
  }
@@ -25,6 +32,9 @@ export function Textarea({
25
32
  error,
26
33
  hint,
27
34
  rows = 4,
35
+ prefixIcon,
36
+ prefixIconNode,
37
+ prefixIconColor,
28
38
  containerStyle,
29
39
  style,
30
40
  onFocus,
@@ -34,40 +44,53 @@ export function Textarea({
34
44
  const { colors } = useTheme()
35
45
  const [focused, setFocused] = useState(false)
36
46
 
47
+ const resolvedPrefixIcon = prefixIcon
48
+ ? renderIcon(prefixIcon, ms(16), prefixIconColor ?? colors.foregroundMuted)
49
+ : prefixIconNode
50
+
37
51
  return (
38
52
  <View style={[styles.container, containerStyle]}>
39
53
  {label ? <Text style={[styles.label, { color: colors.foreground }]} allowFontScaling={true}>{label}</Text> : null}
40
- <TextInput
41
- multiline
42
- numberOfLines={rows}
43
- textAlignVertical="top"
54
+ <View
44
55
  style={[
45
- styles.input,
56
+ styles.inputWrapper,
46
57
  {
47
58
  borderColor: error
48
59
  ? colors.destructive
49
60
  : focused
50
61
  ? (colors.ring ?? colors.primary)
51
62
  : colors.border,
52
- color: colors.foreground,
53
63
  backgroundColor: colors.background,
54
- minHeight: rows * vs(30),
55
64
  },
56
- webInputResetStyle,
57
- style,
58
65
  ]}
59
- onFocus={(e) => {
60
- setFocused(true)
61
- onFocus?.(e)
62
- }}
63
- onBlur={(e) => {
64
- setFocused(false)
65
- onBlur?.(e)
66
- }}
67
- placeholderTextColor={colors.foregroundMuted}
68
- allowFontScaling={true}
69
- {...props}
70
- />
66
+ >
67
+ {resolvedPrefixIcon ? <View style={styles.prefixIcon}>{resolvedPrefixIcon}</View> : null}
68
+ <TextInput
69
+ multiline
70
+ numberOfLines={rows}
71
+ textAlignVertical="top"
72
+ style={[
73
+ styles.input,
74
+ {
75
+ color: colors.foreground,
76
+ minHeight: rows * vs(30),
77
+ },
78
+ webInputResetStyle,
79
+ style,
80
+ ]}
81
+ onFocus={(e) => {
82
+ setFocused(true)
83
+ onFocus?.(e)
84
+ }}
85
+ onBlur={(e) => {
86
+ setFocused(false)
87
+ onBlur?.(e)
88
+ }}
89
+ placeholderTextColor={colors.foregroundMuted}
90
+ allowFontScaling={true}
91
+ {...props}
92
+ />
93
+ </View>
71
94
  {error ? (
72
95
  <Text style={[styles.helperText, { color: colors.destructive }]} allowFontScaling={true}>{error}</Text>
73
96
  ) : null}
@@ -80,23 +103,37 @@ export function Textarea({
80
103
 
81
104
  const styles = StyleSheet.create({
82
105
  container: {
83
- gap: vs(8),
106
+ gap: vs(4),
84
107
  },
85
108
  label: {
86
109
  fontFamily: 'Poppins-Medium',
87
110
  fontSize: ms(13),
111
+ lineHeight: vs(18),
112
+ marginBottom: vs(2),
88
113
  },
89
- input: {
90
- fontFamily: 'Poppins-Regular',
91
- borderWidth: 2,
92
- borderRadius: ms(8),
114
+ inputWrapper: {
115
+ borderWidth: 1,
116
+ borderRadius: 8,
93
117
  paddingHorizontal: s(14),
94
118
  paddingVertical: vs(11),
95
- fontSize: ms(15),
96
- includeFontPadding: false,
119
+ gap: s(8),
120
+ },
121
+ prefixIcon: {
122
+ alignItems: 'flex-start',
123
+ justifyContent: 'flex-start',
124
+ paddingTop: vs(2),
125
+ },
126
+ input: {
127
+ fontFamily: 'Poppins-Regular',
128
+ fontSize: ms(14),
129
+ lineHeight: vs(22),
130
+ padding: 0,
131
+ margin: 0,
97
132
  },
98
133
  helperText: {
99
134
  fontFamily: 'Poppins-Regular',
100
- fontSize: ms(13),
135
+ fontSize: ms(12),
136
+ lineHeight: vs(16),
137
+ marginTop: vs(4),
101
138
  },
102
139
  })