@retray-dev/ui-kit 2.7.0 → 3.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.
- package/COMPONENTS.md +102 -15
- package/README.md +25 -5
- package/dist/index.d.mts +36 -6
- package/dist/index.d.ts +36 -6
- package/dist/index.js +692 -484
- package/dist/index.mjs +622 -415
- package/package.json +6 -3
- package/src/assets/fonts/Poppins-Black.ttf +0 -0
- package/src/assets/fonts/Poppins-BlackItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Bold.ttf +0 -0
- package/src/assets/fonts/Poppins-BoldItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-ExtraBold.ttf +0 -0
- package/src/assets/fonts/Poppins-ExtraBoldItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-ExtraLight.ttf +0 -0
- package/src/assets/fonts/Poppins-ExtraLightItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Italic.ttf +0 -0
- package/src/assets/fonts/Poppins-Light.ttf +0 -0
- package/src/assets/fonts/Poppins-LightItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Medium.ttf +0 -0
- package/src/assets/fonts/Poppins-MediumItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Regular.ttf +0 -0
- package/src/assets/fonts/Poppins-SemiBold.ttf +0 -0
- package/src/assets/fonts/Poppins-SemiBoldItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Thin.ttf +0 -0
- package/src/assets/fonts/Poppins-ThinItalic.ttf +0 -0
- package/src/components/Accordion/Accordion.tsx +16 -9
- package/src/components/AlertBanner/AlertBanner.tsx +35 -35
- package/src/components/Avatar/Avatar.tsx +1 -1
- package/src/components/Badge/Badge.tsx +12 -8
- package/src/components/Button/Button.tsx +9 -9
- package/src/components/Card/Card.tsx +12 -9
- package/src/components/Checkbox/Checkbox.tsx +9 -8
- package/src/components/Chip/Chip.tsx +22 -6
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +86 -38
- package/src/components/CurrencyDisplay/CurrencyDisplay.tsx +1 -1
- package/src/components/CurrencyInput/CurrencyInput.tsx +11 -4
- package/src/components/EmptyState/EmptyState.tsx +2 -1
- package/src/components/IconButton/IconButton.tsx +147 -0
- package/src/components/IconButton/index.ts +2 -0
- package/src/components/Input/Input.tsx +12 -8
- package/src/components/LabelValue/LabelValue.tsx +4 -3
- package/src/components/ListItem/ListItem.tsx +10 -9
- package/src/components/MonthPicker/MonthPicker.tsx +1 -1
- package/src/components/RadioGroup/RadioGroup.tsx +36 -35
- package/src/components/Select/Select.tsx +19 -21
- package/src/components/Sheet/Sheet.tsx +4 -3
- package/src/components/Slider/Slider.tsx +3 -3
- package/src/components/Spinner/Spinner.tsx +36 -2
- package/src/components/Switch/Switch.tsx +4 -4
- package/src/components/Tabs/Tabs.tsx +10 -16
- package/src/components/Text/Text.tsx +6 -6
- package/src/components/Textarea/Textarea.tsx +8 -6
- package/src/components/Toast/Toast.tsx +29 -23
- package/src/components/Toggle/Toggle.tsx +7 -5
- package/src/fonts.ts +30 -0
- package/src/index.ts +1 -0
- package/src/theme/colors.ts +22 -14
- package/src/theme/types.ts +4 -0
- package/src/components/Alert/Alert.tsx +0 -84
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retray-dev/ui-kit",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Personal UI Kit for React Native / Expo",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"import": "./dist/index.mjs",
|
|
12
12
|
"require": "./dist/index.js"
|
|
13
|
-
}
|
|
13
|
+
},
|
|
14
|
+
"./fonts": "./src/fonts.ts"
|
|
14
15
|
},
|
|
15
16
|
"files": [
|
|
16
17
|
"dist",
|
|
@@ -41,6 +42,7 @@
|
|
|
41
42
|
"@gorhom/bottom-sheet": ">=5.0.0",
|
|
42
43
|
"@react-native-community/slider": ">=4.0.0",
|
|
43
44
|
"@react-native-picker/picker": ">=2.0.0",
|
|
45
|
+
"expo-font": ">=14.0.0",
|
|
44
46
|
"expo-haptics": ">=14.0.0",
|
|
45
47
|
"expo-linear-gradient": ">=13.0.0",
|
|
46
48
|
"react": ">=17",
|
|
@@ -49,7 +51,7 @@
|
|
|
49
51
|
"react-native-reanimated": ">=4.0.0",
|
|
50
52
|
"react-native-safe-area-context": ">=4.0.0",
|
|
51
53
|
"react-native-size-matters": ">=0.4.0",
|
|
52
|
-
"react-native-worklets": ">=0.
|
|
54
|
+
"react-native-worklets": ">=0.5.0"
|
|
53
55
|
},
|
|
54
56
|
"pnpm": {
|
|
55
57
|
"overrides": {
|
|
@@ -74,6 +76,7 @@
|
|
|
74
76
|
"eslint-config-prettier": "^10.0.0",
|
|
75
77
|
"eslint-plugin-react": "^7.37.0",
|
|
76
78
|
"eslint-plugin-react-hooks": "^5.0.0",
|
|
79
|
+
"expo-font": "~14.0.11",
|
|
77
80
|
"expo-haptics": "~15.0.8",
|
|
78
81
|
"expo-linear-gradient": "~15.0.8",
|
|
79
82
|
"prettier": "^3.0.0",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -83,7 +83,7 @@ function AccordionItemComponent({
|
|
|
83
83
|
}))
|
|
84
84
|
|
|
85
85
|
return (
|
|
86
|
-
<View style={[styles.item, {
|
|
86
|
+
<View style={[styles.item, { backgroundColor: colors.card, borderColor: colors.border }]}>
|
|
87
87
|
<Pressable
|
|
88
88
|
style={({ pressed }) => [styles.trigger, { opacity: pressed ? 0.6 : 1 }]}
|
|
89
89
|
onPress={() => {
|
|
@@ -91,9 +91,9 @@ function AccordionItemComponent({
|
|
|
91
91
|
onToggle()
|
|
92
92
|
}}
|
|
93
93
|
>
|
|
94
|
-
<Text style={[styles.triggerText, { color: colors.foreground }]}>{item.trigger}</Text>
|
|
94
|
+
<Text style={[styles.triggerText, { color: colors.foreground }]} allowFontScaling={true}>{item.trigger}</Text>
|
|
95
95
|
<Animated.View style={[styles.chevron, rotationStyle]}>
|
|
96
|
-
<Entypo name="chevron-down" size={
|
|
96
|
+
<Entypo name="chevron-down" size={18} color={colors.mutedForeground} />
|
|
97
97
|
</Animated.View>
|
|
98
98
|
</Pressable>
|
|
99
99
|
|
|
@@ -134,7 +134,7 @@ export function Accordion({ items, type = 'single', defaultValue, style }: Accor
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
return (
|
|
137
|
-
<View style={style}>
|
|
137
|
+
<View style={[styles.list, style]}>
|
|
138
138
|
{items.map((item) => (
|
|
139
139
|
<AccordionItemComponent
|
|
140
140
|
key={item.value}
|
|
@@ -148,18 +148,24 @@ export function Accordion({ items, type = 'single', defaultValue, style }: Accor
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
const styles = StyleSheet.create({
|
|
151
|
+
list: {
|
|
152
|
+
gap: s(6),
|
|
153
|
+
},
|
|
151
154
|
item: {
|
|
152
|
-
|
|
155
|
+
borderWidth: 1,
|
|
156
|
+
borderRadius: ms(10),
|
|
157
|
+
overflow: 'hidden',
|
|
153
158
|
},
|
|
154
159
|
trigger: {
|
|
155
160
|
flexDirection: 'row',
|
|
156
161
|
justifyContent: 'space-between',
|
|
157
162
|
alignItems: 'center',
|
|
158
|
-
|
|
163
|
+
paddingHorizontal: s(14),
|
|
164
|
+
paddingVertical: vs(12),
|
|
159
165
|
},
|
|
160
166
|
triggerText: {
|
|
161
|
-
|
|
162
|
-
|
|
167
|
+
fontFamily: 'Poppins-Medium',
|
|
168
|
+
fontSize: ms(14),
|
|
163
169
|
flex: 1,
|
|
164
170
|
},
|
|
165
171
|
chevron: {
|
|
@@ -168,7 +174,8 @@ const styles = StyleSheet.create({
|
|
|
168
174
|
// position:'absolute' is the key — the inner View escapes the animated wrapper's
|
|
169
175
|
// clipped height so onLayout always reports the true content height.
|
|
170
176
|
content: {
|
|
171
|
-
|
|
177
|
+
paddingHorizontal: s(14),
|
|
178
|
+
paddingBottom: vs(12),
|
|
172
179
|
position: 'absolute',
|
|
173
180
|
width: '100%',
|
|
174
181
|
},
|
|
@@ -25,73 +25,73 @@ export interface AlertBannerProps {
|
|
|
25
25
|
export function AlertBanner({ title, description, variant = 'default', icon, iconName, iconColor, style }: AlertBannerProps) {
|
|
26
26
|
const { colors } = useTheme()
|
|
27
27
|
|
|
28
|
-
const
|
|
29
|
-
variant === 'destructive' ? colors.
|
|
30
|
-
: variant === 'success' ? colors.
|
|
31
|
-
: colors.
|
|
28
|
+
const bgColor =
|
|
29
|
+
variant === 'destructive' ? colors.destructiveBorder
|
|
30
|
+
: variant === 'success' ? colors.successBorder
|
|
31
|
+
: colors.card
|
|
32
32
|
|
|
33
|
-
const
|
|
34
|
-
variant === 'destructive' ?
|
|
35
|
-
: variant === 'success' ?
|
|
33
|
+
const textColor =
|
|
34
|
+
variant === 'destructive' ? '#991b1b'
|
|
35
|
+
: variant === 'success' ? '#166534'
|
|
36
36
|
: colors.foreground
|
|
37
37
|
|
|
38
|
-
const
|
|
39
|
-
variant === 'destructive' ? colors.destructive
|
|
40
|
-
: variant === 'success' ? colors.success
|
|
41
|
-
: colors.mutedForeground
|
|
38
|
+
const borderColor = textColor
|
|
42
39
|
|
|
43
40
|
const defaultIcon =
|
|
44
41
|
variant === 'success' ? (
|
|
45
|
-
<FontAwesome5 name="check-circle" size={18} color={
|
|
42
|
+
<FontAwesome5 name="check-circle" size={18} color={textColor} />
|
|
46
43
|
) : variant === 'destructive' ? (
|
|
47
|
-
<MaterialIcons name="error-outline" size={20} color={
|
|
44
|
+
<MaterialIcons name="error-outline" size={20} color={textColor} />
|
|
48
45
|
) : (
|
|
49
|
-
<Entypo name="info-with-circle" size={18} color={
|
|
46
|
+
<Entypo name="info-with-circle" size={18} color={textColor} />
|
|
50
47
|
)
|
|
51
48
|
|
|
52
49
|
const effectiveIcon: React.ReactNode = iconName
|
|
53
|
-
? renderIcon(iconName, 18, iconColor ??
|
|
50
|
+
? renderIcon(iconName, 18, iconColor ?? textColor)
|
|
54
51
|
: icon ?? defaultIcon
|
|
55
52
|
|
|
56
53
|
return (
|
|
57
|
-
<View style={[styles.container, { backgroundColor:
|
|
58
|
-
<View style={styles.
|
|
59
|
-
|
|
60
|
-
{title ? <Text style={[styles.title, { color:
|
|
61
|
-
{description ? (
|
|
62
|
-
<Text style={[styles.description, { color: descColor }]} allowFontScaling={true}>{description}</Text>
|
|
63
|
-
) : null}
|
|
54
|
+
<View style={[styles.container, { backgroundColor: bgColor, borderColor }, style]}>
|
|
55
|
+
<View style={styles.header}>
|
|
56
|
+
<View style={styles.icon}>{effectiveIcon}</View>
|
|
57
|
+
{title ? <Text style={[styles.title, { color: textColor }]} allowFontScaling={true}>{title}</Text> : null}
|
|
64
58
|
</View>
|
|
59
|
+
{description ? (
|
|
60
|
+
<Text style={[styles.description, { color: textColor, opacity: 0.85 }]} allowFontScaling={true}>{description}</Text>
|
|
61
|
+
) : null}
|
|
65
62
|
</View>
|
|
66
63
|
)
|
|
67
64
|
}
|
|
68
65
|
|
|
69
66
|
const styles = StyleSheet.create({
|
|
70
67
|
container: {
|
|
71
|
-
flexDirection: 'row',
|
|
72
68
|
borderWidth: 1,
|
|
73
69
|
borderRadius: ms(12),
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
paddingHorizontal: s(14),
|
|
71
|
+
paddingVertical: vs(12),
|
|
72
|
+
gap: vs(8),
|
|
76
73
|
shadowColor: '#000',
|
|
77
|
-
shadowOffset: { width: 0, height:
|
|
78
|
-
shadowOpacity: 0.
|
|
79
|
-
shadowRadius:
|
|
80
|
-
elevation:
|
|
74
|
+
shadowOffset: { width: 0, height: 3 },
|
|
75
|
+
shadowOpacity: 0.10,
|
|
76
|
+
shadowRadius: 8,
|
|
77
|
+
elevation: 5,
|
|
78
|
+
},
|
|
79
|
+
header: {
|
|
80
|
+
flexDirection: 'row',
|
|
81
|
+
alignItems: 'center',
|
|
82
|
+
gap: s(10),
|
|
81
83
|
},
|
|
82
84
|
icon: {
|
|
83
85
|
marginTop: 0,
|
|
84
86
|
},
|
|
85
|
-
content: {
|
|
86
|
-
flex: 1,
|
|
87
|
-
gap: vs(4),
|
|
88
|
-
},
|
|
89
87
|
title: {
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
fontFamily: 'Poppins-Bold',
|
|
89
|
+
fontSize: ms(15),
|
|
92
90
|
lineHeight: mvs(20),
|
|
91
|
+
flex: 1,
|
|
93
92
|
},
|
|
94
93
|
description: {
|
|
94
|
+
fontFamily: 'Poppins-Regular',
|
|
95
95
|
fontSize: ms(14),
|
|
96
96
|
lineHeight: mvs(20),
|
|
97
97
|
},
|
|
@@ -4,7 +4,7 @@ import { useTheme } from '../../theme'
|
|
|
4
4
|
import { s, vs, ms } from '../../utils/scaling'
|
|
5
5
|
import { renderIcon } from '../../utils/icons'
|
|
6
6
|
|
|
7
|
-
export type BadgeVariant = 'default' | 'secondary' | 'destructive' | 'outline'
|
|
7
|
+
export type BadgeVariant = 'default' | 'secondary' | 'destructive' | 'outline' | 'success' | 'warning' | 'successOutline' | 'destructiveOutline'
|
|
8
8
|
export type BadgeSize = 'sm' | 'md' | 'lg'
|
|
9
9
|
|
|
10
10
|
export interface BadgeProps {
|
|
@@ -53,6 +53,10 @@ export function Badge({ label, children, variant = 'default', size = 'md', icon,
|
|
|
53
53
|
secondary: { backgroundColor: colors.secondary },
|
|
54
54
|
destructive: { backgroundColor: colors.destructive },
|
|
55
55
|
outline: { backgroundColor: 'transparent', borderWidth: 1, borderColor: colors.border },
|
|
56
|
+
success: { backgroundColor: colors.success },
|
|
57
|
+
warning: { backgroundColor: '#f59e0b', },
|
|
58
|
+
successOutline: { backgroundColor: colors.successTint, borderWidth: 1, borderColor: colors.successBorder },
|
|
59
|
+
destructiveOutline: { backgroundColor: colors.destructiveTint, borderWidth: 1, borderColor: colors.destructiveBorder },
|
|
56
60
|
}[variant]
|
|
57
61
|
|
|
58
62
|
const textColor = {
|
|
@@ -60,6 +64,10 @@ export function Badge({ label, children, variant = 'default', size = 'md', icon,
|
|
|
60
64
|
secondary: colors.secondaryForeground,
|
|
61
65
|
destructive: colors.destructiveForeground,
|
|
62
66
|
outline: colors.foreground,
|
|
67
|
+
success: colors.successForeground,
|
|
68
|
+
warning: '#ffffff',
|
|
69
|
+
successOutline: colors.success,
|
|
70
|
+
destructiveOutline: colors.destructive,
|
|
63
71
|
}[variant]
|
|
64
72
|
|
|
65
73
|
const effectiveIcon: React.ReactNode = iconName
|
|
@@ -70,7 +78,7 @@ export function Badge({ label, children, variant = 'default', size = 'md', icon,
|
|
|
70
78
|
|
|
71
79
|
return (
|
|
72
80
|
<View style={[styles.container, containerStyle, sizePadding[size], { gap: sizeIconGap[size] }, style]}>
|
|
73
|
-
{effectiveIcon
|
|
81
|
+
{effectiveIcon}
|
|
74
82
|
{typeof content === 'string' ? (
|
|
75
83
|
<Text style={[styles.label, { color: textColor }, sizeFontSize[size]]} allowFontScaling={true}>
|
|
76
84
|
{content}
|
|
@@ -84,16 +92,12 @@ export function Badge({ label, children, variant = 'default', size = 'md', icon,
|
|
|
84
92
|
|
|
85
93
|
const styles = StyleSheet.create({
|
|
86
94
|
container: {
|
|
87
|
-
borderRadius:
|
|
95
|
+
borderRadius: 9999,
|
|
88
96
|
alignSelf: 'flex-start',
|
|
89
97
|
flexDirection: 'row',
|
|
90
98
|
alignItems: 'center',
|
|
91
99
|
},
|
|
92
|
-
iconContainer: {
|
|
93
|
-
justifyContent: 'center',
|
|
94
|
-
alignItems: 'center',
|
|
95
|
-
},
|
|
96
100
|
label: {
|
|
97
|
-
|
|
101
|
+
fontFamily: 'Poppins-Medium',
|
|
98
102
|
},
|
|
99
103
|
})
|
|
@@ -48,15 +48,15 @@ export interface ButtonProps extends TouchableOpacityProps {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
const containerSizeStyles: Record<ButtonSize, ViewStyle> = {
|
|
51
|
-
sm: { paddingHorizontal: s(
|
|
52
|
-
md: { paddingHorizontal: s(
|
|
53
|
-
lg: { paddingHorizontal: s(
|
|
51
|
+
sm: { paddingHorizontal: s(12), paddingVertical: vs(10), minHeight: 44 },
|
|
52
|
+
md: { paddingHorizontal: s(16), paddingVertical: vs(10), minHeight: 44 },
|
|
53
|
+
lg: { paddingHorizontal: s(20), paddingVertical: vs(12), minHeight: 48 },
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
const labelSizeStyles: Record<ButtonSize, TextStyle> = {
|
|
57
|
-
sm: { fontSize: ms(
|
|
58
|
-
md: { fontSize: ms(
|
|
59
|
-
lg: { fontSize: ms(
|
|
57
|
+
sm: { fontSize: ms(13) },
|
|
58
|
+
md: { fontSize: ms(15) },
|
|
59
|
+
lg: { fontSize: ms(16) },
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
const iconSizeMap: Record<ButtonSize, number> = { sm: 16, md: 18, lg: 20 }
|
|
@@ -148,7 +148,7 @@ export function Button({
|
|
|
148
148
|
) : (
|
|
149
149
|
<>
|
|
150
150
|
{effectiveIcon && iconPosition === 'left' && <>{effectiveIcon}</>}
|
|
151
|
-
<Text style={[styles.label, labelVariantStyle, labelSizeStyles[size], effectiveIcon ? styles.labelWithIcon : undefined]}>{label}</Text>
|
|
151
|
+
<Text style={[styles.label, labelVariantStyle, labelSizeStyles[size], effectiveIcon ? styles.labelWithIcon : undefined]} allowFontScaling={true}>{label}</Text>
|
|
152
152
|
{effectiveIcon && iconPosition === 'right' && <>{effectiveIcon}</>}
|
|
153
153
|
</>
|
|
154
154
|
)}
|
|
@@ -159,7 +159,7 @@ export function Button({
|
|
|
159
159
|
|
|
160
160
|
const styles = StyleSheet.create({
|
|
161
161
|
base: {
|
|
162
|
-
borderRadius:
|
|
162
|
+
borderRadius: 8,
|
|
163
163
|
alignItems: 'center',
|
|
164
164
|
justifyContent: 'center',
|
|
165
165
|
flexDirection: 'row',
|
|
@@ -171,7 +171,7 @@ const styles = StyleSheet.create({
|
|
|
171
171
|
opacity: 0.5,
|
|
172
172
|
},
|
|
173
173
|
label: {
|
|
174
|
-
|
|
174
|
+
fontFamily: 'Poppins-SemiBold',
|
|
175
175
|
},
|
|
176
176
|
labelWithIcon: {
|
|
177
177
|
marginHorizontal: s(8),
|
|
@@ -151,24 +151,27 @@ const styles = StyleSheet.create({
|
|
|
151
151
|
borderWidth: 1,
|
|
152
152
|
},
|
|
153
153
|
header: {
|
|
154
|
-
padding: s(
|
|
154
|
+
padding: s(16),
|
|
155
155
|
paddingBottom: 0,
|
|
156
|
-
gap: vs(
|
|
156
|
+
gap: vs(4),
|
|
157
157
|
},
|
|
158
158
|
title: {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
lineHeight: mvs(
|
|
159
|
+
fontFamily: 'Poppins-SemiBold',
|
|
160
|
+
fontSize: ms(16),
|
|
161
|
+
lineHeight: mvs(22),
|
|
162
162
|
},
|
|
163
163
|
description: {
|
|
164
|
-
|
|
165
|
-
|
|
164
|
+
fontFamily: 'Poppins-Regular',
|
|
165
|
+
fontSize: ms(13),
|
|
166
|
+
lineHeight: mvs(18),
|
|
166
167
|
},
|
|
167
168
|
content: {
|
|
168
|
-
padding: s(
|
|
169
|
+
padding: s(16),
|
|
170
|
+
paddingTop: s(12),
|
|
169
171
|
},
|
|
170
172
|
footer: {
|
|
171
|
-
|
|
173
|
+
paddingHorizontal: s(16),
|
|
174
|
+
paddingBottom: vs(14),
|
|
172
175
|
paddingTop: 0,
|
|
173
176
|
flexDirection: 'row',
|
|
174
177
|
alignItems: 'center',
|
|
@@ -30,11 +30,10 @@ export function Checkbox({
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const handlePressOut = () => {
|
|
33
|
-
Animated.spring(scale, { toValue: 1, useNativeDriver: nativeDriver, speed: 40, bounciness:
|
|
33
|
+
Animated.spring(scale, { toValue: 1, useNativeDriver: nativeDriver, speed: 40, bounciness: 0 }).start()
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
return (
|
|
37
|
-
<Animated.View style={{ transform: [{ scale }] }}>
|
|
38
37
|
<TouchableOpacity
|
|
39
38
|
style={[styles.row, style]}
|
|
40
39
|
onPress={() => {
|
|
@@ -47,29 +46,30 @@ export function Checkbox({
|
|
|
47
46
|
activeOpacity={1}
|
|
48
47
|
touchSoundDisabled={true}
|
|
49
48
|
>
|
|
50
|
-
<View
|
|
49
|
+
<Animated.View
|
|
51
50
|
style={[
|
|
52
51
|
styles.box,
|
|
53
52
|
{
|
|
54
53
|
borderColor: checked ? colors.primary : colors.border,
|
|
55
54
|
backgroundColor: checked ? colors.primary : 'transparent',
|
|
56
55
|
opacity: disabled ? 0.45 : 1,
|
|
56
|
+
transform: [{ scale }],
|
|
57
57
|
},
|
|
58
58
|
]}
|
|
59
59
|
>
|
|
60
60
|
{checked ? (
|
|
61
61
|
<View style={[styles.checkmark, { borderColor: colors.primaryForeground }]} />
|
|
62
62
|
) : null}
|
|
63
|
-
</View>
|
|
63
|
+
</Animated.View>
|
|
64
64
|
{label ? (
|
|
65
65
|
<Text
|
|
66
66
|
style={[styles.label, { color: disabled ? colors.mutedForeground : colors.foreground }]}
|
|
67
|
+
allowFontScaling={true}
|
|
67
68
|
>
|
|
68
69
|
{label}
|
|
69
70
|
</Text>
|
|
70
71
|
) : null}
|
|
71
72
|
</TouchableOpacity>
|
|
72
|
-
</Animated.View>
|
|
73
73
|
)
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -82,7 +82,7 @@ const styles = StyleSheet.create({
|
|
|
82
82
|
box: {
|
|
83
83
|
width: s(24),
|
|
84
84
|
height: s(24),
|
|
85
|
-
borderRadius: ms(
|
|
85
|
+
borderRadius: ms(4),
|
|
86
86
|
borderWidth: 1.5,
|
|
87
87
|
alignItems: 'center',
|
|
88
88
|
justifyContent: 'center',
|
|
@@ -95,7 +95,8 @@ const styles = StyleSheet.create({
|
|
|
95
95
|
transform: [{ rotate: '-45deg' }, { translateY: -1 }],
|
|
96
96
|
},
|
|
97
97
|
label: {
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
fontFamily: 'Poppins-Regular',
|
|
99
|
+
fontSize: ms(14),
|
|
100
|
+
lineHeight: mvs(20),
|
|
100
101
|
},
|
|
101
102
|
})
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { selectionAsync as hapticSelection } from '../../utils/haptics'
|
|
13
13
|
import { useTheme } from '../../theme'
|
|
14
14
|
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
15
|
+
import { renderIcon } from '../../utils/icons'
|
|
15
16
|
|
|
16
17
|
const nativeDriver = Platform.OS !== 'web'
|
|
17
18
|
|
|
@@ -19,6 +20,10 @@ export interface ChipProps {
|
|
|
19
20
|
label: string
|
|
20
21
|
selected?: boolean
|
|
21
22
|
onPress?: () => void
|
|
23
|
+
/** JSX icon rendered before the label. */
|
|
24
|
+
icon?: React.ReactNode
|
|
25
|
+
/** Icon name from @expo/vector-icons resolved automatically. */
|
|
26
|
+
iconName?: string
|
|
22
27
|
style?: ViewStyle
|
|
23
28
|
}
|
|
24
29
|
|
|
@@ -36,7 +41,7 @@ export interface ChipGroupProps {
|
|
|
36
41
|
style?: ViewStyle
|
|
37
42
|
}
|
|
38
43
|
|
|
39
|
-
export function Chip({ label, selected = false, onPress, style }: ChipProps) {
|
|
44
|
+
export function Chip({ label, selected = false, onPress, icon, iconName, style }: ChipProps) {
|
|
40
45
|
const { colors } = useTheme()
|
|
41
46
|
const scale = useRef(new Animated.Value(1)).current
|
|
42
47
|
const pressAnim = useRef(new Animated.Value(selected ? 1 : 0)).current
|
|
@@ -88,6 +93,10 @@ export function Chip({ label, selected = false, onPress, style }: ChipProps) {
|
|
|
88
93
|
outputRange: [colors.border, colors.primary],
|
|
89
94
|
})
|
|
90
95
|
|
|
96
|
+
const resolvedIcon = iconName
|
|
97
|
+
? renderIcon(iconName, ms(13), selected ? colors.primaryForeground : colors.foreground)
|
|
98
|
+
: icon
|
|
99
|
+
|
|
91
100
|
return (
|
|
92
101
|
<Animated.View style={[styles.wrapper, { transform: [{ scale }] }, style]}>
|
|
93
102
|
<TouchableOpacity
|
|
@@ -98,6 +107,7 @@ export function Chip({ label, selected = false, onPress, style }: ChipProps) {
|
|
|
98
107
|
touchSoundDisabled={true}
|
|
99
108
|
>
|
|
100
109
|
<Animated.View style={[styles.chip, { backgroundColor, borderColor }]}>
|
|
110
|
+
{resolvedIcon ? <View style={styles.chipIcon}>{resolvedIcon}</View> : null}
|
|
101
111
|
<Animated.Text style={[styles.label, { color: textColor }]} allowFontScaling={true}>
|
|
102
112
|
{label}
|
|
103
113
|
</Animated.Text>
|
|
@@ -156,15 +166,21 @@ const styles = StyleSheet.create({
|
|
|
156
166
|
chip: {
|
|
157
167
|
borderRadius: 999,
|
|
158
168
|
paddingHorizontal: s(14),
|
|
159
|
-
paddingVertical: vs(
|
|
160
|
-
borderWidth: 1
|
|
169
|
+
paddingVertical: vs(5),
|
|
170
|
+
borderWidth: 1,
|
|
171
|
+
alignItems: 'center',
|
|
172
|
+
justifyContent: 'center',
|
|
173
|
+
flexDirection: 'row',
|
|
174
|
+
gap: s(5),
|
|
175
|
+
},
|
|
176
|
+
chipIcon: {
|
|
161
177
|
alignItems: 'center',
|
|
162
178
|
justifyContent: 'center',
|
|
163
179
|
},
|
|
164
180
|
label: {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
lineHeight: mvs(
|
|
181
|
+
fontFamily: 'Poppins-Medium',
|
|
182
|
+
fontSize: ms(13),
|
|
183
|
+
lineHeight: mvs(18),
|
|
168
184
|
},
|
|
169
185
|
group: {
|
|
170
186
|
flexDirection: 'row',
|