cdslibrary 1.2.11 → 1.2.13

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.
@@ -1,15 +1,11 @@
1
- import React, { useEffect, useRef, useState } from "react";
2
- import { View, Text, Animated, Dimensions, StyleSheet, Pressable, Platform } from "react-native";
1
+ import React, { useEffect, useState } from "react";
2
+ import { View, Text, Animated, Dimensions, StyleSheet, Pressable, Platform, ScrollView } from "react-native";
3
3
  import { CDSButton } from "./CDSButton";
4
-
5
4
  import { MaterialIcons } from "@expo/vector-icons";
6
5
  import { useTheme } from "../context/CDSThemeContext";
7
- import { ScrollView } from "react-native-web";
8
6
  import { LinearGradient } from 'expo-linear-gradient';
9
7
 
10
-
11
8
  const { height, width } = Dimensions.get("window");
12
-
13
9
  const isMobile = width <= 878;
14
10
 
15
11
  export const CDSBottomSheet = ({
@@ -24,90 +20,99 @@ export const CDSBottomSheet = ({
24
20
  secondaryButtonLabel = "Cancelar",
25
21
  onFinish,
26
22
  }) => {
27
-
28
-
29
-
30
23
  const { theme } = useTheme();
31
- const [childHeight, setChildHeight] = useState(0);
32
24
  const [modalVisible, setModalVisible] = useState(isVisible);
33
25
  const [modalOpacity] = useState(new Animated.Value(0));
34
- const [slidePosition] = useState(new Animated.Value(height));
35
-
36
- const handleLayout = (event) => {
37
- const { height: layoutHeight } = event.nativeEvent.layout;
38
- setChildHeight(layoutHeight);
39
- };
40
-
41
- useEffect(() => {
42
- const targetValue = isMobile ? height : width; // Valor fuera de pantalla
26
+ const [slidePosition] = useState(new Animated.Value(isMobile ? height : width));
43
27
 
28
+ // Función unificada para cerrar con animación
29
+ const handleClose = () => {
30
+ const targetValue = isMobile ? height : width;
44
31
 
45
32
  Animated.parallel([
46
33
  Animated.timing(modalOpacity, {
47
- toValue: modalVisible ? 1 : 0,
48
- duration: 400,
34
+ toValue: 0,
35
+ duration: 350,
49
36
  useNativeDriver: false,
50
37
  }),
51
38
  Animated.timing(slidePosition, {
52
- toValue: modalVisible ? 0 : targetValue, // 0 es visible, targetValue es oculto
53
- duration: 400,
39
+ toValue: targetValue,
40
+ duration: 350,
54
41
  useNativeDriver: false,
55
42
  }),
56
- ]).start();
57
- }, [modalVisible, isMobile]); // Añadimos isMobile a las dependencias
43
+ ]).start(() => {
44
+ // Importante: onFinish se ejecuta SOLO cuando la animación termina
45
+ if (onFinish) onFinish();
46
+ setModalVisible(false);
47
+ });
48
+ };
49
+
50
+ useEffect(() => {
51
+ if (modalVisible) {
52
+ Animated.parallel([
53
+ Animated.timing(modalOpacity, {
54
+ toValue: 1,
55
+ duration: 400,
56
+ useNativeDriver: false,
57
+ }),
58
+ Animated.timing(slidePosition, {
59
+ toValue: 0,
60
+ duration: 400,
61
+ useNativeDriver: false,
62
+ }),
63
+ ]).start();
64
+ }
65
+ }, [modalVisible]);
66
+
58
67
  return (
59
68
  <>
60
69
  <Animated.View
61
- onLayout={handleLayout}
62
70
  style={[
63
71
  isMobile ? styles.container.typeBottomSheet : styles.container.typeDrawer,
64
72
  {
65
73
  opacity: modalOpacity,
66
74
  transform: [
67
- isMobile
68
- ? { translateY: slidePosition } // Sube en móvil
69
- : { translateX: slidePosition } // Entra lateral en desktop
75
+ isMobile ? { translateY: slidePosition } : { translateX: slidePosition }
70
76
  ],
71
- backgroundColor: theme.surface.neutral.primary, paddingHorizontal: theme.space.sm,
77
+ backgroundColor: theme.surface.neutral.primary,
78
+ paddingHorizontal: theme.space.sm,
72
79
  paddingTop: theme.space.xl,
73
80
  gap: theme.space.sm,
74
- }, isMobile ? [styles.container.typeBottomSheet, {
75
- borderTopLeftRadius: theme.radius.lg,
76
- borderTopRightRadius: theme.radius.lg,
77
- }] : [styles.container.typeDrawer, {
78
- borderBottomLeftRadius: theme.radius.lg, borderTopLeftRadius: theme.radius.lg, paddingBottom: theme.space.md,
79
- },
80
- ]]}
81
+ ...(isMobile ? {
82
+ borderTopLeftRadius: theme.radius.lg,
83
+ borderTopRightRadius: theme.radius.lg,
84
+ } : {
85
+ borderBottomLeftRadius: theme.radius.lg,
86
+ borderTopLeftRadius: theme.radius.lg,
87
+ paddingBottom: theme.space.md,
88
+ })
89
+ }
90
+ ]}
81
91
  >
82
-
83
92
  {hasClose && (
84
93
  <MaterialIcons
85
- name={"close"}
94
+ name="close"
86
95
  size={theme.typography.icon.lg}
87
96
  color={theme.text.neutral.primary}
88
- onPress={() => {
89
- onFinish && onFinish();
90
- setModalVisible(false);
91
- }}
92
- style={{ position: "absolute", right: theme.space.sm, top: theme.space.sm }}
97
+ onPress={handleClose}
98
+ style={{ position: "absolute", right: theme.space.sm, top: theme.space.sm, zIndex: 10 }}
93
99
  />
94
100
  )}
95
- <Text style={theme.typography.bold.lg}>{title}</Text>
101
+
102
+ {!!title && <Text style={theme.typography.bold.lg}>{title}</Text>}
103
+
96
104
  <View style={styles.scrollWrapper}>
97
105
  <ScrollView
98
106
  style={styles.scrollArea}
99
- contentContainerStyle={[styles.scrollContent, {
100
- flexGrow: 0,
101
- paddingBottom: theme.space.md
102
- }]}
107
+ contentContainerStyle={[styles.scrollContent, { paddingBottom: theme.space.md }]}
103
108
  showsVerticalScrollIndicator={true}
104
- persistentScrollbar={true}
105
- indicatorStyle={theme.name === 'dark' ? 'white' : 'black'}
106
109
  >
107
- {description && (
108
- <Text style={[theme.typography.regular.md, { marginBottom: theme.space.md }]}>{description}</Text>
110
+ {!!description && (
111
+ <Text style={[theme.typography.regular.md, { marginBottom: theme.space.md }]}>
112
+ {description}
113
+ </Text>
109
114
  )}
110
- {customSlot && <View style={styles.customSlot}>{customSlot}</View>}
115
+ {customSlot}
111
116
  </ScrollView>
112
117
  <LinearGradient
113
118
  colors={['transparent', theme.surface.neutral.primary]}
@@ -115,27 +120,28 @@ export const CDSBottomSheet = ({
115
120
  pointerEvents="none"
116
121
  />
117
122
  </View>
123
+
118
124
  {type !== "informative" && (
119
125
  <View style={isMobile ? styles.actionsContainer.typeBottomSheet : styles.actionsContainer.typeDrawer}>
120
126
  <CDSButton
121
127
  label={primaryButtonLabel}
122
128
  onPress={() => {
123
- primaryButtonOnPress && primaryButtonOnPress();
124
- setModalVisible(false)
125
- }
126
- }
129
+ if (primaryButtonOnPress) primaryButtonOnPress();
130
+ handleClose();
131
+ }}
127
132
  />
128
133
  <CDSButton
129
134
  label={secondaryButtonLabel}
130
135
  type="ghost"
131
136
  onPress={() => {
132
137
  onFinish && onFinish();
133
- setModalVisible(false);
138
+ handleClose;
134
139
  }}
135
140
  />
136
141
  </View>
137
142
  )}
138
143
  </Animated.View>
144
+
139
145
  <Animated.View
140
146
  style={[
141
147
  styles.overlay,
@@ -145,103 +151,77 @@ export const CDSBottomSheet = ({
145
151
  },
146
152
  ]}
147
153
  >
148
- <Pressable onPress={() => setModalVisible(false)} style={{ flex: 1 }} />
154
+ <Pressable onPress={() => {
155
+ onFinish && onFinish();
156
+ handleClose;
157
+ }} style={{ flex: 1 }} />
149
158
  </Animated.View>
150
159
  </>
151
160
  );
152
- }
161
+ };
153
162
 
154
163
  const styles = StyleSheet.create({
155
164
  overlay: {
156
165
  position: "absolute",
157
166
  top: 0,
158
167
  left: 0,
159
- width: "100%",
160
- height: "100%"
168
+ right: 0,
169
+ bottom: 0,
170
+ zIndex: 98,
161
171
  },
162
-
163
172
  container: {
164
173
  typeBottomSheet: {
165
174
  maxHeight: '90%',
166
- flex: 1,
167
- justifyContent: "flex-end",
168
- alignItems: "center",
169
- zIndex: 99,
170
175
  width: "100%",
171
176
  position: "absolute",
172
177
  bottom: 0,
178
+ left: 0,
179
+ right: 0,
180
+ zIndex: 99,
173
181
  },
174
182
  typeDrawer: {
175
- position: "absolute", // Clave para el Drawer
176
- right: 0, // Anclado a la derecha
183
+ position: "absolute",
184
+ right: 0,
177
185
  top: 0,
178
186
  bottom: 0,
179
- justifyContent: "center",
180
- zIndex: 99,
181
187
  width: 600,
188
+ zIndex: 99,
189
+ ...Platform.select({
190
+ web: { boxShadow: '-10px 0px 15px rgba(0,0,0,0.1)' }
191
+ })
182
192
  },
183
193
  },
184
-
185
194
  scrollWrapper: {
186
- flex: 1, // Ocupa todo el espacio vertical disponible
187
- position: 'relative', // Para que el gradiente se posicione absolutamente dentro de él
195
+ flex: 1,
196
+ position: 'relative',
188
197
  width: '100%',
189
198
  },
190
199
  scrollArea: {
191
- flexShrink: 1,
192
- flexGrow: 1,
200
+ flex: 1,
193
201
  width: '100%',
194
- paddingBottom: 20,
195
202
  },
196
-
197
203
  scrollContent: {
198
- paddingBottom: 20, // Aire al final del contenido
199
204
  gap: 16,
200
205
  },
201
-
202
206
  fadeGradient: {
203
207
  position: 'absolute',
204
208
  bottom: 0,
205
209
  left: 0,
206
210
  right: 0,
207
- height: 60, // Ajusta la altura del gradiente según tu diseño
208
- },
209
-
210
- infoContainer: {
211
- typeBottomSheet: {
212
- width: "100%",
213
- zIndex: 100,
214
- pointerEvents: "all",
215
- },
216
- typeDrawer: {
217
- flex: 1, // Ocupa todo el alto disponible en el Drawer
218
- width: "100%",
219
- zIndex: 100,
220
- pointerEvents: "all",
221
- // Opcional: una sombra elegante para Desktop
222
- ...Platform.select({
223
- web: { boxShadow: '-10px 0px 15px rgba(0,0,0,0.2)' }
224
- })
225
- },
211
+ height: 40,
226
212
  },
227
213
  actionsContainer: {
228
214
  typeBottomSheet: {
229
- flex: "row",
215
+ flexDirection: "row",
230
216
  width: "100%",
231
217
  gap: 8,
218
+ paddingBottom: 20,
232
219
  },
233
220
  typeDrawer: {
234
- marginTop: 'auto',
235
221
  flexDirection: "row-reverse",
236
222
  width: "100%",
237
223
  gap: 8,
224
+ marginTop: 'auto',
238
225
  },
239
226
  },
240
-
241
- customSlot: {
242
- width: '100%',
243
- height: 'auto',
244
- },
245
-
246
- });
247
-
227
+ });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cdslibrary",
3
3
  "license": "0BSD",
4
- "version": "1.2.11",
4
+ "version": "1.2.13",
5
5
  "main": "index.js",
6
6
  "author": "Nat Viramontes",
7
7
  "description": "A library of components for the CDS project",