@retray-dev/ui-kit 2.5.1 → 2.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COMPONENTS.md +2 -2
- package/dist/index.js +374 -362
- package/dist/index.mjs +362 -331
- package/package.json +23 -21
- package/src/components/Accordion/Accordion.tsx +61 -57
- package/src/components/Alert/Alert.tsx +11 -10
- package/src/components/AlertBanner/AlertBanner.tsx +9 -8
- package/src/components/Avatar/Avatar.tsx +9 -8
- package/src/components/Badge/Badge.tsx +11 -10
- package/src/components/Button/Button.tsx +10 -9
- package/src/components/Card/Card.tsx +12 -11
- package/src/components/Checkbox/Checkbox.tsx +16 -13
- package/src/components/Chip/Chip.tsx +8 -7
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +12 -11
- package/src/components/CurrencyDisplay/CurrencyDisplay.tsx +2 -1
- package/src/components/CurrencyInput/CurrencyInput.tsx +2 -1
- package/src/components/EmptyState/EmptyState.tsx +19 -18
- package/src/components/Input/Input.tsx +15 -14
- package/src/components/LabelValue/LabelValue.tsx +6 -5
- package/src/components/ListItem/ListItem.tsx +20 -19
- package/src/components/MonthPicker/MonthPicker.tsx +9 -8
- package/src/components/Progress/Progress.tsx +2 -1
- package/src/components/RadioGroup/RadioGroup.tsx +18 -15
- package/src/components/Select/Select.tsx +25 -24
- package/src/components/Sheet/Sheet.tsx +15 -14
- package/src/components/Slider/Slider.tsx +7 -6
- package/src/components/Switch/Switch.tsx +7 -6
- package/src/components/Tabs/Tabs.tsx +17 -14
- package/src/components/Text/Text.tsx +7 -6
- package/src/components/Textarea/Textarea.tsx +9 -8
- package/src/components/Toast/Toast.tsx +19 -18
- package/src/components/Toggle/Toggle.tsx +9 -8
- package/src/utils/haptics.ts +32 -0
- package/src/utils/scaling.ts +26 -0
|
@@ -2,6 +2,7 @@ import React from 'react'
|
|
|
2
2
|
import { Modal, View, Text, StyleSheet, TouchableOpacity } from 'react-native'
|
|
3
3
|
import { useTheme } from '../../theme'
|
|
4
4
|
import { Button } from '../Button'
|
|
5
|
+
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
5
6
|
|
|
6
7
|
export interface ConfirmDialogProps {
|
|
7
8
|
visible: boolean
|
|
@@ -57,14 +58,14 @@ const styles = StyleSheet.create({
|
|
|
57
58
|
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
58
59
|
justifyContent: 'center',
|
|
59
60
|
alignItems: 'center',
|
|
60
|
-
padding: 24,
|
|
61
|
+
padding: s(24),
|
|
61
62
|
},
|
|
62
63
|
dialog: {
|
|
63
64
|
width: '100%',
|
|
64
|
-
maxWidth: 400,
|
|
65
|
-
borderRadius: 16,
|
|
66
|
-
padding: 24,
|
|
67
|
-
gap: 12,
|
|
65
|
+
maxWidth: s(400),
|
|
66
|
+
borderRadius: ms(16),
|
|
67
|
+
padding: s(24),
|
|
68
|
+
gap: vs(12),
|
|
68
69
|
shadowColor: '#000',
|
|
69
70
|
shadowOffset: { width: 0, height: 8 },
|
|
70
71
|
shadowOpacity: 0.15,
|
|
@@ -72,16 +73,16 @@ const styles = StyleSheet.create({
|
|
|
72
73
|
elevation: 8,
|
|
73
74
|
},
|
|
74
75
|
title: {
|
|
75
|
-
fontSize: 18,
|
|
76
|
+
fontSize: ms(18),
|
|
76
77
|
fontWeight: '600',
|
|
77
|
-
lineHeight: 26,
|
|
78
|
+
lineHeight: mvs(26),
|
|
78
79
|
},
|
|
79
80
|
description: {
|
|
80
|
-
fontSize: 15,
|
|
81
|
-
lineHeight: 22,
|
|
81
|
+
fontSize: ms(15),
|
|
82
|
+
lineHeight: mvs(22),
|
|
82
83
|
},
|
|
83
84
|
actions: {
|
|
84
|
-
gap: 10,
|
|
85
|
-
marginTop: 8,
|
|
85
|
+
gap: vs(10),
|
|
86
|
+
marginTop: vs(8),
|
|
86
87
|
},
|
|
87
88
|
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { View, Text, StyleSheet, ViewStyle } from 'react-native'
|
|
3
3
|
import { useTheme } from '../../theme'
|
|
4
|
+
import { ms } from '../../utils/scaling'
|
|
4
5
|
|
|
5
6
|
export interface CurrencyDisplayProps {
|
|
6
7
|
value: number | string
|
|
@@ -42,7 +43,7 @@ export function CurrencyDisplay({ value, prefix = '$', showDecimals = false, tex
|
|
|
42
43
|
const styles = StyleSheet.create({
|
|
43
44
|
container: {},
|
|
44
45
|
amount: {
|
|
45
|
-
fontSize: 56,
|
|
46
|
+
fontSize: ms(56),
|
|
46
47
|
fontWeight: '700',
|
|
47
48
|
},
|
|
48
49
|
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { ViewStyle, TextStyle } from 'react-native'
|
|
3
3
|
import { Input } from '../Input'
|
|
4
|
+
import { ms } from '../../utils/scaling'
|
|
4
5
|
|
|
5
6
|
export interface CurrencyInputProps {
|
|
6
7
|
value?: string
|
|
@@ -54,7 +55,7 @@ export function CurrencyInput({
|
|
|
54
55
|
onChangeValue?.(isNaN(raw) ? 0 : raw)
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
const inputStyle: TextStyle = size === 'large' ? { fontSize: 36 } : {}
|
|
58
|
+
const inputStyle: TextStyle = size === 'large' ? { fontSize: ms(36) } : {}
|
|
58
59
|
|
|
59
60
|
return (
|
|
60
61
|
<Input
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { View, Text, StyleSheet, ViewStyle } from 'react-native'
|
|
3
3
|
import { useTheme } from '../../theme'
|
|
4
|
+
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
4
5
|
|
|
5
6
|
export interface EmptyStateProps {
|
|
6
7
|
icon?: React.ReactNode
|
|
@@ -58,45 +59,45 @@ const styles = StyleSheet.create({
|
|
|
58
59
|
justifyContent: 'center',
|
|
59
60
|
borderWidth: 1,
|
|
60
61
|
borderStyle: 'dashed',
|
|
61
|
-
borderRadius: 12,
|
|
62
|
-
padding: 32,
|
|
63
|
-
gap: 16,
|
|
62
|
+
borderRadius: ms(12),
|
|
63
|
+
padding: s(32),
|
|
64
|
+
gap: vs(16),
|
|
64
65
|
},
|
|
65
66
|
containerCompact: {
|
|
66
|
-
padding: 20,
|
|
67
|
-
gap: 10,
|
|
67
|
+
padding: s(20),
|
|
68
|
+
gap: vs(10),
|
|
68
69
|
},
|
|
69
70
|
iconWrapper: {
|
|
70
|
-
width: 48,
|
|
71
|
-
height: 48,
|
|
72
|
-
borderRadius: 12,
|
|
71
|
+
width: s(48),
|
|
72
|
+
height: s(48),
|
|
73
|
+
borderRadius: ms(12),
|
|
73
74
|
alignItems: 'center',
|
|
74
75
|
justifyContent: 'center',
|
|
75
76
|
},
|
|
76
77
|
iconWrapperCompact: {
|
|
77
|
-
width: 36,
|
|
78
|
-
height: 36,
|
|
79
|
-
borderRadius: 8,
|
|
78
|
+
width: s(36),
|
|
79
|
+
height: s(36),
|
|
80
|
+
borderRadius: ms(8),
|
|
80
81
|
},
|
|
81
82
|
textWrapper: {
|
|
82
83
|
alignItems: 'center',
|
|
83
|
-
gap: 8,
|
|
84
|
-
maxWidth: 320,
|
|
84
|
+
gap: vs(8),
|
|
85
|
+
maxWidth: s(320),
|
|
85
86
|
},
|
|
86
87
|
title: {
|
|
87
|
-
fontSize: 18,
|
|
88
|
+
fontSize: ms(18),
|
|
88
89
|
fontWeight: '500',
|
|
89
90
|
textAlign: 'center',
|
|
90
91
|
},
|
|
91
92
|
titleCompact: {
|
|
92
|
-
fontSize: 15,
|
|
93
|
+
fontSize: ms(15),
|
|
93
94
|
},
|
|
94
95
|
description: {
|
|
95
|
-
fontSize: 14,
|
|
96
|
-
lineHeight: 20,
|
|
96
|
+
fontSize: ms(14),
|
|
97
|
+
lineHeight: mvs(20),
|
|
97
98
|
textAlign: 'center',
|
|
98
99
|
},
|
|
99
100
|
action: {
|
|
100
|
-
marginTop: 8,
|
|
101
|
+
marginTop: vs(8),
|
|
101
102
|
},
|
|
102
103
|
})
|
|
@@ -2,6 +2,7 @@ import React, { useState } from 'react'
|
|
|
2
2
|
import { TextInput, View, Text, StyleSheet, TextInputProps, ViewStyle, TextStyle, TouchableOpacity, Platform } from 'react-native'
|
|
3
3
|
import { AntDesign } from '@expo/vector-icons'
|
|
4
4
|
import { useTheme } from '../../theme'
|
|
5
|
+
import { s, vs, ms } from '../../utils/scaling'
|
|
5
6
|
|
|
6
7
|
const webInputResetStyle: any =
|
|
7
8
|
Platform.OS === 'web'
|
|
@@ -112,43 +113,43 @@ export function Input({ label, error, hint, prefix, suffix, prefixStyle, suffixS
|
|
|
112
113
|
|
|
113
114
|
const styles = StyleSheet.create({
|
|
114
115
|
container: {
|
|
115
|
-
gap: 8,
|
|
116
|
+
gap: vs(8),
|
|
116
117
|
},
|
|
117
118
|
label: {
|
|
118
|
-
fontSize: 15,
|
|
119
|
+
fontSize: ms(15),
|
|
119
120
|
fontWeight: '500',
|
|
120
121
|
},
|
|
121
122
|
inputWrapper: {
|
|
122
123
|
flexDirection: 'row',
|
|
123
124
|
alignItems: 'center',
|
|
124
125
|
borderWidth: 1.5,
|
|
125
|
-
borderRadius: 8,
|
|
126
|
-
paddingHorizontal: 16,
|
|
127
|
-
paddingVertical: 14,
|
|
126
|
+
borderRadius: ms(8),
|
|
127
|
+
paddingHorizontal: s(16),
|
|
128
|
+
paddingVertical: vs(14),
|
|
128
129
|
},
|
|
129
130
|
input: {
|
|
130
131
|
flex: 1,
|
|
131
|
-
fontSize: 17,
|
|
132
|
+
fontSize: ms(17),
|
|
132
133
|
paddingVertical: 0,
|
|
133
134
|
},
|
|
134
135
|
prefixContainer: {
|
|
135
|
-
marginRight: 8,
|
|
136
|
+
marginRight: s(8),
|
|
136
137
|
},
|
|
137
138
|
prefixText: {
|
|
138
|
-
fontSize: 17,
|
|
139
|
-
marginRight: 8,
|
|
139
|
+
fontSize: ms(17),
|
|
140
|
+
marginRight: s(8),
|
|
140
141
|
},
|
|
141
142
|
suffixContainer: {
|
|
142
|
-
marginLeft: 8,
|
|
143
|
+
marginLeft: s(8),
|
|
143
144
|
},
|
|
144
145
|
suffixText: {
|
|
145
|
-
fontSize: 17,
|
|
146
|
-
marginLeft: 8,
|
|
146
|
+
fontSize: ms(17),
|
|
147
|
+
marginLeft: s(8),
|
|
147
148
|
},
|
|
148
149
|
passwordToggle: {
|
|
149
|
-
padding: 4,
|
|
150
|
+
padding: s(4),
|
|
150
151
|
},
|
|
151
152
|
helperText: {
|
|
152
|
-
fontSize: 13,
|
|
153
|
+
fontSize: ms(13),
|
|
153
154
|
},
|
|
154
155
|
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { View, Text, StyleSheet, ViewStyle } from 'react-native'
|
|
3
3
|
import { useTheme } from '../../theme'
|
|
4
|
+
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
4
5
|
|
|
5
6
|
export interface LabelValueProps {
|
|
6
7
|
label: string
|
|
@@ -32,16 +33,16 @@ const styles = StyleSheet.create({
|
|
|
32
33
|
flexDirection: 'row',
|
|
33
34
|
justifyContent: 'space-between',
|
|
34
35
|
alignItems: 'center',
|
|
35
|
-
gap: 12,
|
|
36
|
+
gap: s(12),
|
|
36
37
|
},
|
|
37
38
|
label: {
|
|
38
|
-
fontSize: 13,
|
|
39
|
-
lineHeight: 18,
|
|
39
|
+
fontSize: ms(13),
|
|
40
|
+
lineHeight: mvs(18),
|
|
40
41
|
},
|
|
41
42
|
value: {
|
|
42
|
-
fontSize: 15,
|
|
43
|
+
fontSize: ms(15),
|
|
43
44
|
fontWeight: '500',
|
|
44
|
-
lineHeight: 22,
|
|
45
|
+
lineHeight: mvs(22),
|
|
45
46
|
textAlign: 'right',
|
|
46
47
|
},
|
|
47
48
|
})
|
|
@@ -10,8 +10,9 @@ import {
|
|
|
10
10
|
Platform,
|
|
11
11
|
} from 'react-native'
|
|
12
12
|
import { Entypo } from '@expo/vector-icons'
|
|
13
|
-
import
|
|
13
|
+
import { selectionAsync as hapticSelection } from '../../utils/haptics'
|
|
14
14
|
import { useTheme } from '../../theme'
|
|
15
|
+
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
15
16
|
|
|
16
17
|
const nativeDriver = Platform.OS !== 'web'
|
|
17
18
|
|
|
@@ -104,7 +105,7 @@ export function ListItem({
|
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
const handlePress = () => {
|
|
107
|
-
|
|
108
|
+
hapticSelection()
|
|
108
109
|
onPress?.()
|
|
109
110
|
}
|
|
110
111
|
|
|
@@ -192,7 +193,7 @@ export function ListItem({
|
|
|
192
193
|
<View
|
|
193
194
|
style={[
|
|
194
195
|
styles.separator,
|
|
195
|
-
{ backgroundColor: colors.border, marginLeft: effectiveLeft ? 16 + 44 + 12 : 16 },
|
|
196
|
+
{ backgroundColor: colors.border, marginLeft: effectiveLeft ? s(16) + s(44) + s(12) : s(16) },
|
|
196
197
|
]}
|
|
197
198
|
/>
|
|
198
199
|
) : null}
|
|
@@ -204,52 +205,52 @@ const styles = StyleSheet.create({
|
|
|
204
205
|
container: {
|
|
205
206
|
flexDirection: 'row',
|
|
206
207
|
alignItems: 'center',
|
|
207
|
-
paddingHorizontal: 16,
|
|
208
|
-
paddingVertical: 14,
|
|
209
|
-
gap: 12,
|
|
208
|
+
paddingHorizontal: s(16),
|
|
209
|
+
paddingVertical: vs(14),
|
|
210
|
+
gap: s(12),
|
|
210
211
|
},
|
|
211
212
|
leftContainer: {
|
|
212
|
-
width: 44,
|
|
213
|
-
height: 44,
|
|
213
|
+
width: s(44),
|
|
214
|
+
height: s(44),
|
|
214
215
|
alignItems: 'center',
|
|
215
216
|
justifyContent: 'center',
|
|
216
217
|
flexShrink: 0,
|
|
217
218
|
},
|
|
218
219
|
content: {
|
|
219
220
|
flex: 1,
|
|
220
|
-
gap: 4,
|
|
221
|
+
gap: vs(4),
|
|
221
222
|
},
|
|
222
223
|
title: {
|
|
223
|
-
fontSize: 17,
|
|
224
|
+
fontSize: ms(17),
|
|
224
225
|
fontWeight: '500',
|
|
225
|
-
lineHeight: 24,
|
|
226
|
+
lineHeight: mvs(24),
|
|
226
227
|
},
|
|
227
228
|
subtitle: {
|
|
228
|
-
fontSize: 14,
|
|
229
|
+
fontSize: ms(14),
|
|
229
230
|
fontWeight: '400',
|
|
230
|
-
lineHeight: 20,
|
|
231
|
+
lineHeight: mvs(20),
|
|
231
232
|
},
|
|
232
233
|
caption: {
|
|
233
|
-
fontSize: 12,
|
|
234
|
+
fontSize: ms(12),
|
|
234
235
|
fontWeight: '400',
|
|
235
|
-
lineHeight: 16,
|
|
236
|
+
lineHeight: mvs(16),
|
|
236
237
|
opacity: 0.7,
|
|
237
238
|
},
|
|
238
239
|
rightContainer: {
|
|
239
240
|
alignItems: 'flex-end',
|
|
240
241
|
justifyContent: 'center',
|
|
241
242
|
flexShrink: 0,
|
|
242
|
-
maxWidth: 160,
|
|
243
|
+
maxWidth: s(160),
|
|
243
244
|
},
|
|
244
245
|
rightText: {
|
|
245
|
-
fontSize: 15,
|
|
246
|
+
fontSize: ms(15),
|
|
246
247
|
},
|
|
247
248
|
chevron: {
|
|
248
|
-
marginLeft: 4,
|
|
249
|
+
marginLeft: s(4),
|
|
249
250
|
},
|
|
250
251
|
separator: {
|
|
251
252
|
height: StyleSheet.hairlineWidth,
|
|
252
|
-
marginRight: 16,
|
|
253
|
+
marginRight: s(16),
|
|
253
254
|
},
|
|
254
255
|
disabled: {
|
|
255
256
|
opacity: 0.45,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { View, Text, TouchableOpacity, StyleSheet, ViewStyle } from 'react-native'
|
|
3
3
|
import { Entypo } from '@expo/vector-icons'
|
|
4
|
-
import
|
|
4
|
+
import { selectionAsync as hapticSelection } from '../../utils/haptics'
|
|
5
5
|
import { useTheme } from '../../theme'
|
|
6
|
+
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
6
7
|
|
|
7
8
|
const MONTH_NAMES = [
|
|
8
9
|
'January', 'February', 'March', 'April', 'May', 'June',
|
|
@@ -25,7 +26,7 @@ export function MonthPicker({ value, onChange, style }: MonthPickerProps) {
|
|
|
25
26
|
const { colors } = useTheme()
|
|
26
27
|
|
|
27
28
|
const handlePrev = () => {
|
|
28
|
-
|
|
29
|
+
hapticSelection()
|
|
29
30
|
if (value.month === 1) {
|
|
30
31
|
onChange({ month: 12, year: value.year - 1 })
|
|
31
32
|
} else {
|
|
@@ -34,7 +35,7 @@ export function MonthPicker({ value, onChange, style }: MonthPickerProps) {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
const handleNext = () => {
|
|
37
|
-
|
|
38
|
+
hapticSelection()
|
|
38
39
|
if (value.month === 12) {
|
|
39
40
|
onChange({ month: 1, year: value.year + 1 })
|
|
40
41
|
} else {
|
|
@@ -74,16 +75,16 @@ const styles = StyleSheet.create({
|
|
|
74
75
|
justifyContent: 'space-between',
|
|
75
76
|
},
|
|
76
77
|
arrow: {
|
|
77
|
-
width: 44,
|
|
78
|
-
height: 44,
|
|
78
|
+
width: s(44),
|
|
79
|
+
height: s(44),
|
|
79
80
|
alignItems: 'center',
|
|
80
81
|
justifyContent: 'center',
|
|
81
82
|
},
|
|
82
83
|
label: {
|
|
83
|
-
fontSize: 17,
|
|
84
|
+
fontSize: ms(17),
|
|
84
85
|
fontWeight: '500',
|
|
85
|
-
lineHeight: 24,
|
|
86
|
+
lineHeight: mvs(24),
|
|
86
87
|
textAlign: 'center',
|
|
87
|
-
minWidth: 160,
|
|
88
|
+
minWidth: s(160),
|
|
88
89
|
},
|
|
89
90
|
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useRef, useState, useEffect } from 'react'
|
|
2
2
|
import { View, Animated, StyleSheet, ViewStyle } from 'react-native'
|
|
3
3
|
import { useTheme } from '../../theme'
|
|
4
|
+
import { vs } from '../../utils/scaling'
|
|
4
5
|
|
|
5
6
|
export interface ProgressProps {
|
|
6
7
|
/** Current progress value. Clamped to `[0, max]`. Defaults to `0`. */
|
|
@@ -40,7 +41,7 @@ export function Progress({ value = 0, max = 100, style }: ProgressProps) {
|
|
|
40
41
|
|
|
41
42
|
const styles = StyleSheet.create({
|
|
42
43
|
track: {
|
|
43
|
-
height: 8,
|
|
44
|
+
height: vs(8),
|
|
44
45
|
borderRadius: 999,
|
|
45
46
|
overflow: 'hidden',
|
|
46
47
|
width: '100%',
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import React, { useRef } from 'react'
|
|
2
|
-
import { TouchableOpacity, Animated, View, Text, StyleSheet, ViewStyle } from 'react-native'
|
|
3
|
-
import
|
|
2
|
+
import { TouchableOpacity, Animated, View, Text, StyleSheet, ViewStyle, Platform } from 'react-native'
|
|
3
|
+
import { selectionAsync as hapticSelection } from '../../utils/haptics'
|
|
4
|
+
|
|
5
|
+
const nativeDriver = Platform.OS !== 'web'
|
|
4
6
|
import { useTheme } from '../../theme'
|
|
7
|
+
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
5
8
|
|
|
6
9
|
export interface RadioOption {
|
|
7
10
|
label: string
|
|
@@ -31,11 +34,11 @@ function RadioItem({
|
|
|
31
34
|
|
|
32
35
|
const handlePressIn = () => {
|
|
33
36
|
if (option.disabled) return
|
|
34
|
-
Animated.spring(scale, { toValue: 0.95, useNativeDriver:
|
|
37
|
+
Animated.spring(scale, { toValue: 0.95, useNativeDriver: nativeDriver, speed: 40, bounciness: 0 }).start()
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
const handlePressOut = () => {
|
|
38
|
-
Animated.spring(scale, { toValue: 1, useNativeDriver:
|
|
41
|
+
Animated.spring(scale, { toValue: 1, useNativeDriver: nativeDriver, speed: 40, bounciness: 4 }).start()
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
return (
|
|
@@ -44,7 +47,7 @@ function RadioItem({
|
|
|
44
47
|
style={styles.row}
|
|
45
48
|
onPress={() => {
|
|
46
49
|
if (!option.disabled) {
|
|
47
|
-
|
|
50
|
+
hapticSelection()
|
|
48
51
|
onSelect()
|
|
49
52
|
}
|
|
50
53
|
}}
|
|
@@ -101,7 +104,7 @@ export function RadioGroup({
|
|
|
101
104
|
|
|
102
105
|
const styles = StyleSheet.create({
|
|
103
106
|
container: {
|
|
104
|
-
gap: 12,
|
|
107
|
+
gap: vs(12),
|
|
105
108
|
},
|
|
106
109
|
horizontal: {
|
|
107
110
|
flexDirection: 'row',
|
|
@@ -110,23 +113,23 @@ const styles = StyleSheet.create({
|
|
|
110
113
|
row: {
|
|
111
114
|
flexDirection: 'row',
|
|
112
115
|
alignItems: 'center',
|
|
113
|
-
gap: 12,
|
|
116
|
+
gap: s(12),
|
|
114
117
|
},
|
|
115
118
|
radio: {
|
|
116
|
-
width: 24,
|
|
117
|
-
height: 24,
|
|
118
|
-
borderRadius: 12,
|
|
119
|
+
width: s(24),
|
|
120
|
+
height: s(24),
|
|
121
|
+
borderRadius: s(12),
|
|
119
122
|
borderWidth: 1.5,
|
|
120
123
|
alignItems: 'center',
|
|
121
124
|
justifyContent: 'center',
|
|
122
125
|
},
|
|
123
126
|
dot: {
|
|
124
|
-
width: 10,
|
|
125
|
-
height: 10,
|
|
126
|
-
borderRadius: 5,
|
|
127
|
+
width: s(10),
|
|
128
|
+
height: s(10),
|
|
129
|
+
borderRadius: s(5),
|
|
127
130
|
},
|
|
128
131
|
label: {
|
|
129
|
-
fontSize: 14,
|
|
130
|
-
lineHeight: 20,
|
|
132
|
+
fontSize: ms(14),
|
|
133
|
+
lineHeight: mvs(20),
|
|
131
134
|
},
|
|
132
135
|
})
|
|
@@ -2,8 +2,9 @@ import React, { useRef, useState } from 'react'
|
|
|
2
2
|
import { View, Text, TouchableOpacity, Modal, Animated, StyleSheet, ViewStyle, Platform } from 'react-native'
|
|
3
3
|
import { Picker } from '@react-native-picker/picker'
|
|
4
4
|
import { Entypo } from '@expo/vector-icons'
|
|
5
|
-
import
|
|
5
|
+
import { selectionAsync as hapticSelection } from '../../utils/haptics'
|
|
6
6
|
import { useTheme } from '../../theme'
|
|
7
|
+
import { s, vs, ms } from '../../utils/scaling'
|
|
7
8
|
|
|
8
9
|
const isIOS = Platform.OS === 'ios'
|
|
9
10
|
const isAndroid = Platform.OS === 'android'
|
|
@@ -55,7 +56,7 @@ export function Select({
|
|
|
55
56
|
|
|
56
57
|
const handleOpen = () => {
|
|
57
58
|
if (disabled) return
|
|
58
|
-
|
|
59
|
+
hapticSelection()
|
|
59
60
|
if (isIOS) {
|
|
60
61
|
setPendingValue(value)
|
|
61
62
|
setPickerVisible(true)
|
|
@@ -70,7 +71,7 @@ export function Select({
|
|
|
70
71
|
|
|
71
72
|
const handleConfirm = () => {
|
|
72
73
|
if (pendingValue !== undefined && pendingValue !== '') {
|
|
73
|
-
|
|
74
|
+
hapticSelection()
|
|
74
75
|
onValueChange?.(pendingValue)
|
|
75
76
|
}
|
|
76
77
|
setPickerVisible(false)
|
|
@@ -165,7 +166,7 @@ export function Select({
|
|
|
165
166
|
selectedValue={value ?? ''}
|
|
166
167
|
onValueChange={(val) => {
|
|
167
168
|
if (val !== '') {
|
|
168
|
-
|
|
169
|
+
hapticSelection()
|
|
169
170
|
onValueChange?.(val as string)
|
|
170
171
|
}
|
|
171
172
|
}}
|
|
@@ -227,10 +228,10 @@ export function Select({
|
|
|
227
228
|
|
|
228
229
|
const styles = StyleSheet.create({
|
|
229
230
|
container: {
|
|
230
|
-
gap: 8,
|
|
231
|
+
gap: vs(8),
|
|
231
232
|
},
|
|
232
233
|
label: {
|
|
233
|
-
fontSize: 15,
|
|
234
|
+
fontSize: ms(15),
|
|
234
235
|
fontWeight: '500',
|
|
235
236
|
},
|
|
236
237
|
trigger: {
|
|
@@ -238,9 +239,9 @@ const styles = StyleSheet.create({
|
|
|
238
239
|
alignItems: 'center',
|
|
239
240
|
justifyContent: 'space-between',
|
|
240
241
|
borderWidth: 1.5,
|
|
241
|
-
borderRadius: 8,
|
|
242
|
-
paddingHorizontal: 16,
|
|
243
|
-
paddingVertical: 14,
|
|
242
|
+
borderRadius: ms(8),
|
|
243
|
+
paddingHorizontal: s(16),
|
|
244
|
+
paddingVertical: vs(14),
|
|
244
245
|
shadowColor: '#000',
|
|
245
246
|
shadowOffset: { width: 0, height: 1 },
|
|
246
247
|
shadowOpacity: 0.04,
|
|
@@ -248,41 +249,41 @@ const styles = StyleSheet.create({
|
|
|
248
249
|
elevation: 1,
|
|
249
250
|
},
|
|
250
251
|
triggerText: {
|
|
251
|
-
fontSize: 17,
|
|
252
|
+
fontSize: ms(17),
|
|
252
253
|
flex: 1,
|
|
253
254
|
},
|
|
254
255
|
chevron: {
|
|
255
|
-
marginLeft: 8,
|
|
256
|
+
marginLeft: s(8),
|
|
256
257
|
},
|
|
257
258
|
helperText: {
|
|
258
|
-
fontSize: 13,
|
|
259
|
+
fontSize: ms(13),
|
|
259
260
|
},
|
|
260
261
|
iosBackdrop: {
|
|
261
262
|
flex: 1,
|
|
262
263
|
backgroundColor: 'rgba(0,0,0,0.4)',
|
|
263
264
|
},
|
|
264
265
|
iosSheet: {
|
|
265
|
-
borderTopLeftRadius: 16,
|
|
266
|
-
borderTopRightRadius: 16,
|
|
267
|
-
paddingBottom: 32,
|
|
266
|
+
borderTopLeftRadius: ms(16),
|
|
267
|
+
borderTopRightRadius: ms(16),
|
|
268
|
+
paddingBottom: vs(32),
|
|
268
269
|
},
|
|
269
270
|
iosToolbar: {
|
|
270
271
|
flexDirection: 'row',
|
|
271
272
|
alignItems: 'center',
|
|
272
273
|
justifyContent: 'space-between',
|
|
273
|
-
paddingHorizontal: 16,
|
|
274
|
-
paddingVertical: 12,
|
|
274
|
+
paddingHorizontal: s(16),
|
|
275
|
+
paddingVertical: vs(12),
|
|
275
276
|
borderBottomWidth: 1,
|
|
276
277
|
},
|
|
277
278
|
iosToolbarTitle: {
|
|
278
|
-
fontSize: 17,
|
|
279
|
+
fontSize: ms(17),
|
|
279
280
|
fontWeight: '600',
|
|
280
281
|
},
|
|
281
282
|
iosDoneBtn: {
|
|
282
|
-
padding: 4,
|
|
283
|
+
padding: s(4),
|
|
283
284
|
},
|
|
284
285
|
iosDoneBtnText: {
|
|
285
|
-
fontSize: 17,
|
|
286
|
+
fontSize: ms(17),
|
|
286
287
|
fontWeight: '600',
|
|
287
288
|
},
|
|
288
289
|
androidHiddenPicker: {
|
|
@@ -292,9 +293,9 @@ const styles = StyleSheet.create({
|
|
|
292
293
|
},
|
|
293
294
|
webPicker: {
|
|
294
295
|
borderWidth: 1.5,
|
|
295
|
-
borderRadius: 8,
|
|
296
|
-
paddingHorizontal: 16,
|
|
297
|
-
paddingVertical: 14,
|
|
298
|
-
fontSize: 17,
|
|
296
|
+
borderRadius: ms(8),
|
|
297
|
+
paddingHorizontal: s(16),
|
|
298
|
+
paddingVertical: vs(14),
|
|
299
|
+
fontSize: ms(17),
|
|
299
300
|
},
|
|
300
301
|
})
|
|
@@ -7,8 +7,9 @@ import {
|
|
|
7
7
|
BottomSheetModalProvider,
|
|
8
8
|
type BottomSheetBackdropProps,
|
|
9
9
|
} from '@gorhom/bottom-sheet'
|
|
10
|
-
import
|
|
10
|
+
import { impactLight } from '../../utils/haptics'
|
|
11
11
|
import { useTheme } from '../../theme'
|
|
12
|
+
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
12
13
|
|
|
13
14
|
export { BottomSheetModalProvider }
|
|
14
15
|
|
|
@@ -41,7 +42,7 @@ export function Sheet({
|
|
|
41
42
|
|
|
42
43
|
useEffect(() => {
|
|
43
44
|
if (open) {
|
|
44
|
-
|
|
45
|
+
impactLight()
|
|
45
46
|
ref.current?.present()
|
|
46
47
|
} else {
|
|
47
48
|
ref.current?.dismiss()
|
|
@@ -88,28 +89,28 @@ export function Sheet({
|
|
|
88
89
|
|
|
89
90
|
const styles = StyleSheet.create({
|
|
90
91
|
background: {
|
|
91
|
-
borderTopLeftRadius: 16,
|
|
92
|
-
borderTopRightRadius: 16,
|
|
92
|
+
borderTopLeftRadius: ms(16),
|
|
93
|
+
borderTopRightRadius: ms(16),
|
|
93
94
|
},
|
|
94
95
|
handle: {
|
|
95
|
-
width: 36,
|
|
96
|
-
height: 4,
|
|
97
|
-
borderRadius: 2,
|
|
96
|
+
width: s(36),
|
|
97
|
+
height: vs(4),
|
|
98
|
+
borderRadius: ms(2),
|
|
98
99
|
},
|
|
99
100
|
content: {
|
|
100
|
-
paddingHorizontal: 24,
|
|
101
|
-
paddingBottom: 32,
|
|
101
|
+
paddingHorizontal: s(24),
|
|
102
|
+
paddingBottom: vs(32),
|
|
102
103
|
},
|
|
103
104
|
header: {
|
|
104
|
-
gap: 8,
|
|
105
|
-
marginBottom: 16,
|
|
105
|
+
gap: vs(8),
|
|
106
|
+
marginBottom: vs(16),
|
|
106
107
|
},
|
|
107
108
|
title: {
|
|
108
|
-
fontSize: 18,
|
|
109
|
+
fontSize: ms(18),
|
|
109
110
|
fontWeight: '600',
|
|
110
111
|
},
|
|
111
112
|
description: {
|
|
112
|
-
fontSize: 14,
|
|
113
|
-
lineHeight: 20,
|
|
113
|
+
fontSize: ms(14),
|
|
114
|
+
lineHeight: mvs(20),
|
|
114
115
|
},
|
|
115
116
|
})
|