ikualo-ui-kit-mobile 2.1.17 → 2.1.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/app.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "ikualo-app-2.0",
4
4
  "slug": "ikualo-app-20",
5
5
  "owner": "ikualo",
6
- "version": "2.1.17",
6
+ "version": "2.1.19",
7
7
  "orientation": "portrait",
8
8
  "icon": "./assets/icon.png",
9
9
  "userInterfaceStyle": "automatic",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ikualo-ui-kit-mobile",
3
- "version": "2.1.17",
3
+ "version": "2.1.19",
4
4
  "main": "src/index.ts",
5
5
  "scripts": {
6
6
  "start": "expo start",
@@ -1,6 +1,16 @@
1
1
  import { Icon, Text } from 'react-native-paper';
2
2
  import { getStylesDialog } from '../../../assets/styles/elements/dialog';
3
- import { View, TouchableWithoutFeedback, Modal, Keyboard, TouchableHighlight, Animated } from 'react-native';
3
+ import {
4
+ View,
5
+ TouchableWithoutFeedback,
6
+ Modal,
7
+ Keyboard,
8
+ TouchableHighlight,
9
+ Animated,
10
+ BackHandler,
11
+ Platform,
12
+ InteractionManager,
13
+ } from 'react-native';
4
14
  import { useEffect, useState, useRef } from 'react';
5
15
  import useStore from '../../store';
6
16
  import { IDialogDown } from '../../models';
@@ -8,7 +18,7 @@ import { IDialogDown } from '../../models';
8
18
  // Sistema simple de prioridades global
9
19
  class PriorityManager {
10
20
  private static instance: PriorityManager;
11
- private currentDialog: { id: string; priority: number; onDismiss: () => void } | null = null;
21
+ private currentDialog: { id: string; priority: number; onDismiss?: () => void } | null = null;
12
22
  private readonly listeners: Set<() => void> = new Set();
13
23
 
14
24
  static getInstance(): PriorityManager {
@@ -27,10 +37,10 @@ class PriorityManager {
27
37
  this.listeners.forEach((listener) => listener());
28
38
  }
29
39
 
30
- showDialog(id: string, priority: number, onDismiss: () => void) {
40
+ showDialog(id: string, priority: number, onDismiss?: () => void) {
31
41
  // Si hay un diálogo actual y el nuevo tiene mayor prioridad, cerrar el actual
32
42
  if (this.currentDialog && priority > this.currentDialog.priority) {
33
- this.currentDialog.onDismiss();
43
+ this.currentDialog.onDismiss?.();
34
44
  this.currentDialog = null;
35
45
  }
36
46
 
@@ -65,6 +75,7 @@ export const DialogDown = (props: IDialogDown & { priority?: 0 | 1 | 2 | 3 | 4 |
65
75
  const { isVisible, title, children, onDismiss, image, showCloseButton = true, priority = 0, id } = props;
66
76
  const slideAnim = useRef(new Animated.Value(0)).current;
67
77
  const [currentDialog, setCurrentDialog] = useState<{ id: string; priority: number } | null>(null);
78
+ const [isAnimationReady, setIsAnimationReady] = useState(false);
68
79
  const [dialogId] = useState(() => {
69
80
  // Si se proporciona un id, usarlo. Si no, generar uno aleatorio
70
81
  return id || Math.random().toString(36).substring(2, 11);
@@ -103,17 +114,32 @@ export const DialogDown = (props: IDialogDown & { priority?: 0 | 1 | 2 | 3 | 4 |
103
114
  };
104
115
  }, [dialogId]);
105
116
 
106
- // Animación basada en si este diálogo es el actual
107
117
  useEffect(() => {
108
118
  const isCurrentDialog = currentDialog?.id === dialogId;
109
119
  if (isCurrentDialog) {
110
- Animated.timing(slideAnim, {
111
- toValue: 1,
112
- duration: 300,
113
- useNativeDriver: true,
114
- }).start();
120
+ setIsAnimationReady(false);
121
+ slideAnim.setValue(0);
122
+ const handle = InteractionManager.runAfterInteractions(() => {
123
+ requestAnimationFrame(() => {
124
+ requestAnimationFrame(() => {
125
+ if (currentDialog?.id === dialogId) {
126
+ setIsAnimationReady(true);
127
+ Animated.timing(slideAnim, {
128
+ toValue: 1,
129
+ duration: 300,
130
+ useNativeDriver: true,
131
+ }).start();
132
+ }
133
+ });
134
+ });
135
+ });
136
+
137
+ return () => {
138
+ handle.cancel();
139
+ };
115
140
  } else {
116
141
  slideAnim.setValue(0);
142
+ setIsAnimationReady(false);
117
143
  }
118
144
  }, [currentDialog, slideAnim, dialogId]);
119
145
 
@@ -129,16 +155,38 @@ export const DialogDown = (props: IDialogDown & { priority?: 0 | 1 | 2 | 3 | 4 |
129
155
  };
130
156
  }, []);
131
157
 
158
+ useEffect(() => {
159
+ if (Platform.OS === 'android' && !onDismiss && isVisible) {
160
+ const backHandler = BackHandler.addEventListener('hardwareBackPress', () => {
161
+ // Si no hay onDismiss, prevenir el cierre
162
+ return true;
163
+ });
164
+ return () => backHandler.remove();
165
+ }
166
+ }, [isVisible, onDismiss]);
167
+
132
168
  const handleDismiss = () => {
133
169
  priorityManager.current.hideDialog(dialogId);
134
- onDismiss();
170
+ onDismiss?.();
171
+ };
172
+
173
+ const handleRequestClose = () => {
174
+ if (onDismiss) {
175
+ handleDismiss();
176
+ }
177
+ // Si no hay onDismiss, no hacer nada - previene el cierre
135
178
  };
136
179
 
137
180
  // Solo renderizar si este diálogo es el actual
138
181
  const isCurrentDialog = Boolean(isVisible && currentDialog && currentDialog.id === dialogId);
139
182
 
140
183
  return (
141
- <Modal visible={isCurrentDialog} transparent={true} animationType="none" onRequestClose={handleDismiss}>
184
+ <Modal
185
+ visible={isCurrentDialog}
186
+ transparent={true}
187
+ animationType="none"
188
+ onRequestClose={handleRequestClose}
189
+ >
142
190
  <TouchableWithoutFeedback onPress={handleDismissKeyboard}>
143
191
  <View style={stylesDialog.modalBackground}>
144
192
  <Animated.View
@@ -154,6 +202,7 @@ export const DialogDown = (props: IDialogDown & { priority?: 0 | 1 | 2 | 3 | 4 |
154
202
  }),
155
203
  },
156
204
  ],
205
+ opacity: isAnimationReady ? 1 : 0,
157
206
  },
158
207
  ]}
159
208
  >
@@ -64,8 +64,19 @@ export const DialogExamples = () => {
64
64
  setIsVisible2(true);
65
65
  }}
66
66
  />
67
- <DialogDown isVisible={isVisible2} onDismiss={() => setIsVisible2(false)} title="Titulo de prueba">
67
+ <DialogDown
68
+ isVisible={isVisible2}
69
+ showCloseButton={false}
70
+ title="Titulo de prueba"
71
+ //onDismiss={() => setIsVisible2(false)}
72
+ >
68
73
  <Text>Texto de prueba</Text>
74
+ <BtnContained
75
+ text="Aceptar"
76
+ onPress={() => {
77
+ setIsVisible2(false);
78
+ }}
79
+ />
69
80
  </DialogDown>
70
81
  <BtnContained
71
82
  text="Modal bajo animacion"
@@ -125,7 +125,7 @@ export interface IDialogDown {
125
125
  title?: string;
126
126
  showCloseButton?: boolean;
127
127
  children: any;
128
- onDismiss: () => void;
128
+ onDismiss?: () => void;
129
129
  style?: ViewStyle;
130
130
  image?: React.ReactNode;
131
131
  priority?: 0 | 1 | 2 | 3 | 4 | 5;