cdslibrary 1.2.85 → 1.2.86

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.
@@ -5,66 +5,84 @@ import Animated, {
5
5
  useSharedValue,
6
6
  withSequence,
7
7
  withTiming,
8
+ withDelay,
8
9
  interpolateColor
9
10
  } from "react-native-reanimated";
10
11
  import { useTheme } from "../context/CDSThemeContext";
11
12
 
13
+ const AnimatedTextInput = Animated.createAnimatedComponent(TextInput);
14
+
12
15
  export const CDSInput = ({ label, type, keyboard, placeholder, value, onChangeText, animationTrigger, returnKeyType, onFocus }) => {
13
16
  const { theme } = useTheme();
14
17
  const [isFocused, setIsFocused] = useState(false);
15
18
 
16
19
  const flashValue = useSharedValue(0);
20
+ const textHighlight = useSharedValue(0);
17
21
  const isInternalChange = useRef(false);
18
22
 
23
+ const isReadOnly = type === 'readOnly';
24
+
25
+ // --- Colores de seguridad ---
26
+ const colorBase = theme?.text?.neutral?.primary
27
+ const colorReadOnlyText = theme?.text?.neutral?.secondary
28
+ const colorFocus = theme?.surface?.special?.progress
29
+ const colorTertiary = theme?.outline?.neutral?.tertiaryVariant
30
+ const colorPrimaryOutline = theme?.outline?.neutral?.primary
31
+
19
32
  useEffect(() => {
20
- if (!isInternalChange.current) {
21
- flashValue.value = withSequence(
22
- withTiming(1, { duration: 200 }),
33
+ // ELIMINAMOS la restricción de !isReadOnly para que se anime siempre
34
+ if (!isInternalChange.current && value) {
35
+ flashValue.value = withDelay(400, withSequence(
36
+ withTiming(1, { duration: 400 }),
37
+ withTiming(0, { duration: 600 })
38
+ ));
39
+
40
+ textHighlight.value = withSequence(
41
+ withTiming(1, { duration: 400 }),
23
42
  withTiming(0, { duration: 600 })
24
43
  );
25
44
  }
26
45
  isInternalChange.current = false;
27
- }, [value, animationTrigger]);
28
-
29
- const handleTextChange = (inputText) => {
30
- isInternalChange.current = true;
31
-
32
- if (keyboard === "decimal-pad") {
33
- let cleaned = inputText.replace(',', '.').replace(/[^0-9.]/g, "");
34
- const parts = cleaned.split('.');
35
- if (parts.length > 2) cleaned = parts[0] + '.' + parts.slice(1).join('');
36
- onChangeText && onChangeText(cleaned);
37
- } else {
38
- onChangeText && onChangeText(inputText);
39
- }
40
- };
46
+ }, [value, animationTrigger]); // Quitamos isReadOnly de las dependencias para evitar disparos extra
41
47
 
42
48
  const animatedBoxStyle = useAnimatedStyle(() => {
43
49
  const borderColor = interpolateColor(
44
50
  flashValue.value,
45
51
  [0, 1],
46
52
  [
47
- isFocused ? theme.outline.neutral.focus : value ? theme.outline.neutral.tertiaryVariant : theme.outline.neutral.primary,
48
- theme.outline.neutral.focus
53
+ isFocused ? colorFocus : value ? colorTertiary : colorPrimaryOutline,
54
+ colorFocus
49
55
  ]
50
56
  );
51
57
 
52
58
  return {
53
- borderColor: borderColor,
54
- // Quitamos el scale momentáneamente para asegurar que el layout no brinque
55
- // transform: [{ scale: 1 + flashValue.value * 0.01 }],
56
- borderWidth: 1 + (flashValue.value * 1),
59
+ borderColor,
60
+ borderWidth: 1 + (flashValue.value * 2),
61
+ transform: [{ scale: 1 + (flashValue.value * 0.06) }]
57
62
  };
58
63
  });
59
64
 
65
+ const animatedTextStyle = useAnimatedStyle(() => {
66
+ // Definimos el color inicial según si es readOnly o no
67
+ const startColor = isReadOnly ? colorReadOnlyText : colorBase;
68
+
69
+ return {
70
+ color: interpolateColor(
71
+ textHighlight.value,
72
+ [0, 1],
73
+ [startColor, colorFocus] // El color de "brillo" sigue siendo el de foco
74
+ ),
75
+ letterSpacing: textHighlight.value * 1,
76
+ opacity: isReadOnly ? 0.85 + (textHighlight.value * 0.3) : 0.8 + (textHighlight.value * 0.2),
77
+ };
78
+ });
79
+
80
+ if (!theme) return null;
60
81
 
61
82
  return (
62
83
  <View style={styles.container}>
63
84
  {label && (
64
- <Text style={[
65
- theme.typography.label,
66
- { color: theme.text.neutral.primary, marginBottom: theme.space.xs }
67
- ]}>
85
+ <Text style={[theme.typography.label, { color: colorBase, marginBottom: theme.space?.xs || 4 }]}>
68
86
  {label}
69
87
  </Text>
70
88
  )}
@@ -73,35 +91,34 @@ export const CDSInput = ({ label, type, keyboard, placeholder, value, onChangeTe
73
91
  styles.wrapper,
74
92
  animatedBoxStyle,
75
93
  {
76
- backgroundColor: type === 'readOnly' ? theme.surface.neutral.primaryVariant : theme.surface.neutral.primary,
77
- borderRadius: theme.radius.sm,
94
+ backgroundColor: isReadOnly ? theme.surface.neutral.primaryVariant : theme.surface.neutral.primary,
95
+ borderRadius: theme.radius?.sm || 8,
78
96
  }
79
97
  ]}>
80
- <TextInput
98
+ <AnimatedTextInput
81
99
  style={[
82
100
  styles.textBox,
83
- theme.typography.inputText.value,
101
+ theme.typography.inputText?.value,
102
+ animatedTextStyle,
84
103
  {
85
- paddingHorizontal: theme.space.sm,
86
- color: type === 'readOnly' ? theme.text.neutral.secondary : theme.text.neutral.primary,
87
- // Fix para web:
88
- ...Platform.select({
89
- web: { outlineStyle: 'none' }
90
- })
104
+ paddingHorizontal: theme.space?.sm || 12,
105
+ fontWeight: '600',
106
+ ...Platform.select({ web: { outlineStyle: 'none' } })
91
107
  },
92
108
  ]}
93
109
  placeholder={placeholder}
94
110
  placeholderTextColor={theme.text.neutral.placeholder}
95
111
  keyboardType={keyboard}
96
- onChangeText={handleTextChange}
112
+ onChangeText={(txt) => {
113
+ isInternalChange.current = true;
114
+ onChangeText && onChangeText(txt);
115
+ }}
97
116
  value={value}
98
- editable={type !== 'readOnly'}
117
+ editable={!isReadOnly}
99
118
  secureTextEntry={type === "password"}
100
- onFocus={() => { setIsFocused(true); onFocus }}
119
+ onFocus={() => { setIsFocused(true); onFocus && onFocus(); }}
101
120
  onBlur={() => setIsFocused(false)}
102
121
  underlineColorAndroid="transparent"
103
- returnKeyType={returnKeyType}
104
- dataSet={{ lpignore: "true" }}
105
122
  />
106
123
  </Animated.View>
107
124
  </View>
@@ -109,20 +126,14 @@ export const CDSInput = ({ label, type, keyboard, placeholder, value, onChangeTe
109
126
  };
110
127
 
111
128
  const styles = StyleSheet.create({
112
- container: {
113
- width: "100%",
114
- alignSelf: 'stretch',
115
- },
129
+ container: { width: "100%", alignSelf: 'stretch' },
116
130
  wrapper: {
117
131
  width: '100%',
118
132
  height: 48,
119
- flexDirection: 'row', // Asegura que el TextInput interno tenga un eje claro
133
+ flexDirection: 'row',
120
134
  alignItems: 'center',
121
135
  borderWidth: 1,
136
+ overflow: 'hidden'
122
137
  },
123
- textBox: {
124
- flex: 1, // Esto es lo más importante: ocupa todo el espacio sobrante
125
- height: '100%',
126
- width: '100%',
127
- },
138
+ textBox: { flex: 1, height: '100%', width: '100%' },
128
139
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cdslibrary",
3
3
  "license": "0BSD",
4
- "version": "1.2.85",
4
+ "version": "1.2.86",
5
5
  "main": "index.js",
6
6
  "author": "Nat Viramontes",
7
7
  "description": "A library of components for the CDS project",