@xetwa/design-system 1.0.17 → 1.0.19
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/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import { View, Pressable } from 'react-native';
|
|
3
3
|
import type { ViewStyle, DimensionValue } from 'react-native';
|
|
4
|
+
import Animated, { useAnimatedStyle, withTiming } from 'react-native-reanimated';
|
|
4
5
|
import { theme } from '../../../styles/theme';
|
|
5
6
|
import { useResponsive } from '../../../hooks/useResponsive';
|
|
6
7
|
|
|
8
|
+
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
|
|
9
|
+
|
|
7
10
|
/**
|
|
8
11
|
* Cartão base e fundacional do Design System.
|
|
9
12
|
* Fornece a estrutura comum de bordas, fundos, sombras e estados interativos
|
|
@@ -112,12 +115,9 @@ export const BaseCard = ({
|
|
|
112
115
|
}
|
|
113
116
|
: getShadowStyle();
|
|
114
117
|
|
|
115
|
-
// Consolidate card styles with responsive scaling
|
|
116
|
-
const
|
|
117
|
-
backgroundColor: activeBg,
|
|
118
|
+
// Consolidate static card styles with responsive scaling
|
|
119
|
+
const staticCardStyle: ViewStyle = {
|
|
118
120
|
borderRadius: scale(borderRadius),
|
|
119
|
-
borderWidth: borderWidth === 0 && !isSelected ? 0 : activeBorderWidth,
|
|
120
|
-
borderColor: activeBorderColor,
|
|
121
121
|
borderStyle,
|
|
122
122
|
padding: padding !== undefined ? scale(padding) : undefined,
|
|
123
123
|
paddingVertical: padding === undefined ? scale(paddingVertical) : undefined,
|
|
@@ -130,26 +130,35 @@ export const BaseCard = ({
|
|
|
130
130
|
...activeShadow,
|
|
131
131
|
};
|
|
132
132
|
|
|
133
|
+
const animatedStyleProps = useAnimatedStyle(() => {
|
|
134
|
+
return {
|
|
135
|
+
backgroundColor: withTiming(activeBg, { duration: 250 }),
|
|
136
|
+
borderColor: withTiming(activeBorderColor, { duration: 250 }),
|
|
137
|
+
borderWidth: withTiming(borderWidth === 0 && !isSelected ? 0 : activeBorderWidth, { duration: 250 }),
|
|
138
|
+
};
|
|
139
|
+
}, [activeBg, activeBorderColor, activeBorderWidth, isSelected, borderWidth]);
|
|
140
|
+
|
|
133
141
|
if (onPress) {
|
|
134
142
|
return (
|
|
135
|
-
<
|
|
143
|
+
<AnimatedPressable
|
|
136
144
|
onPress={onPress}
|
|
137
145
|
disabled={disabled}
|
|
138
|
-
style={(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
146
|
+
style={(state) => [
|
|
147
|
+
staticCardStyle,
|
|
148
|
+
animatedStyleProps,
|
|
149
|
+
state.pressed && !disabled && { opacity: 0.9 },
|
|
150
|
+
...(Array.isArray(style) ? style : [style].filter(Boolean) as any[]),
|
|
142
151
|
]}
|
|
143
152
|
>
|
|
144
153
|
{children}
|
|
145
|
-
</
|
|
154
|
+
</AnimatedPressable>
|
|
146
155
|
);
|
|
147
156
|
}
|
|
148
157
|
|
|
149
158
|
return (
|
|
150
|
-
<View style={[
|
|
159
|
+
<Animated.View style={[staticCardStyle, animatedStyleProps, style]}>
|
|
151
160
|
{children}
|
|
152
|
-
</View>
|
|
161
|
+
</Animated.View>
|
|
153
162
|
);
|
|
154
163
|
};
|
|
155
164
|
|
|
@@ -30,6 +30,8 @@ export interface PlanCardProps {
|
|
|
30
30
|
isPopular?: boolean;
|
|
31
31
|
/** Texto customizado para o badge (ex: "POUPA 40%") */
|
|
32
32
|
badgeText?: string;
|
|
33
|
+
/** Define se o plano está selecionado */
|
|
34
|
+
isSelected?: boolean;
|
|
33
35
|
/** Estilização customizada do container. */
|
|
34
36
|
style?: ViewStyle | ViewStyle[];
|
|
35
37
|
/** Variante de layout do cartão (completo ou miniatura). */
|
|
@@ -46,6 +48,7 @@ export const PlanCard = ({
|
|
|
46
48
|
excludedItems = [],
|
|
47
49
|
isPopular = false,
|
|
48
50
|
badgeText,
|
|
51
|
+
isSelected = false,
|
|
49
52
|
style,
|
|
50
53
|
variant = 'default',
|
|
51
54
|
}: PlanCardProps) => {
|
|
@@ -141,6 +144,7 @@ export const PlanCard = ({
|
|
|
141
144
|
paddingHorizontal={config.paddingHorizontal}
|
|
142
145
|
shadow={config.shadow}
|
|
143
146
|
overflow={config.overflow}
|
|
147
|
+
isSelected={isSelected}
|
|
144
148
|
style={[
|
|
145
149
|
config.flatShadow ? styles.fluentFlatShadow : null,
|
|
146
150
|
config.customShadow ? config.customShadow : null,
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { View, StyleSheet, Pressable, Platform } from 'react-native';
|
|
2
2
|
import type { ViewStyle } from 'react-native';
|
|
3
|
+
import Animated, { useAnimatedStyle, withTiming } from 'react-native-reanimated';
|
|
3
4
|
import { theme } from '../../../styles/theme';
|
|
4
5
|
import type { ReactNode } from 'react';
|
|
5
6
|
import { useResponsive } from '../../../hooks/useResponsive';
|
|
6
7
|
import { Typography } from '../../Typography/Typography';
|
|
7
8
|
|
|
9
|
+
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
|
|
10
|
+
|
|
8
11
|
/**
|
|
9
12
|
* Cartão genérico para selecionar opções simples, usado frequentemente em formulários de Onboarding.
|
|
10
13
|
*/
|
|
@@ -29,35 +32,49 @@ export const SelectionCard = ({
|
|
|
29
32
|
}: SelectionCardProps) => {
|
|
30
33
|
const { scale, scaleText } = useResponsive();
|
|
31
34
|
|
|
35
|
+
const containerAnimatedStyle = useAnimatedStyle(() => {
|
|
36
|
+
return {
|
|
37
|
+
backgroundColor: withTiming(selected ? theme.colors.primaryLight : theme.colors.white, { duration: 250 }),
|
|
38
|
+
borderColor: withTiming(selected ? theme.colors.primary : theme.colors.brown[100], { duration: 250 }),
|
|
39
|
+
};
|
|
40
|
+
}, [selected]);
|
|
41
|
+
|
|
42
|
+
const iconBoxAnimatedStyle = useAnimatedStyle(() => {
|
|
43
|
+
return {
|
|
44
|
+
backgroundColor: withTiming(selected ? theme.colors.primary : theme.colors.brown[50], { duration: 250 }),
|
|
45
|
+
};
|
|
46
|
+
}, [selected]);
|
|
47
|
+
|
|
32
48
|
return (
|
|
33
|
-
<
|
|
49
|
+
<AnimatedPressable
|
|
34
50
|
style={[
|
|
35
51
|
styles.container,
|
|
36
|
-
selected
|
|
52
|
+
selected && styles.selectedShadow,
|
|
37
53
|
{
|
|
38
54
|
padding: scale(16),
|
|
39
55
|
borderRadius: scale(16),
|
|
40
56
|
},
|
|
57
|
+
containerAnimatedStyle,
|
|
41
58
|
style,
|
|
42
59
|
]}
|
|
43
60
|
onPress={onPress}
|
|
44
61
|
>
|
|
45
62
|
{iconNode && (
|
|
46
|
-
<View style={[
|
|
63
|
+
<Animated.View style={[
|
|
47
64
|
styles.iconBox,
|
|
48
|
-
selected ? styles.selectedIconBox : styles.defaultIconBox,
|
|
49
65
|
{
|
|
50
66
|
width: scale(44),
|
|
51
67
|
height: scale(44),
|
|
52
68
|
borderRadius: scale(12),
|
|
53
69
|
marginRight: scale(16),
|
|
54
|
-
}
|
|
70
|
+
},
|
|
71
|
+
iconBoxAnimatedStyle
|
|
55
72
|
]}>
|
|
56
73
|
{iconNode}
|
|
57
|
-
</View>
|
|
74
|
+
</Animated.View>
|
|
58
75
|
)}
|
|
59
76
|
<Typography weight="bold" style={[styles.label, { fontSize: scaleText(16) }]}>{label}</Typography>
|
|
60
|
-
</
|
|
77
|
+
</AnimatedPressable>
|
|
61
78
|
);
|
|
62
79
|
};
|
|
63
80
|
|
|
@@ -72,12 +89,8 @@ const styles = StyleSheet.create({
|
|
|
72
89
|
width: '100%',
|
|
73
90
|
},
|
|
74
91
|
defaultContainer: {
|
|
75
|
-
borderColor: theme.colors.brown[100],
|
|
76
|
-
backgroundColor: theme.colors.white,
|
|
77
92
|
},
|
|
78
|
-
|
|
79
|
-
borderColor: theme.colors.primary,
|
|
80
|
-
backgroundColor: theme.colors.primaryLight,
|
|
93
|
+
selectedShadow: {
|
|
81
94
|
...Platform.select({
|
|
82
95
|
web: { boxShadow: `0px 4px 0px rgba(242, 151, 75, 0.3)` },
|
|
83
96
|
default: {
|
|
@@ -97,12 +110,6 @@ const styles = StyleSheet.create({
|
|
|
97
110
|
justifyContent: 'center',
|
|
98
111
|
marginRight: 16,
|
|
99
112
|
},
|
|
100
|
-
defaultIconBox: {
|
|
101
|
-
backgroundColor: theme.colors.brown[50],
|
|
102
|
-
},
|
|
103
|
-
selectedIconBox: {
|
|
104
|
-
backgroundColor: theme.colors.primary,
|
|
105
|
-
},
|
|
106
113
|
label: {
|
|
107
114
|
|
|
108
115
|
fontSize: 16,
|