ikualo-ui-kit-mobile 2.1.16 → 2.1.18
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
package/package.json
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { Icon, Text } from 'react-native-paper';
|
|
2
2
|
import { getStylesDialog } from '../../../assets/styles/elements/dialog';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
View,
|
|
5
|
+
TouchableWithoutFeedback,
|
|
6
|
+
Modal,
|
|
7
|
+
Keyboard,
|
|
8
|
+
TouchableHighlight,
|
|
9
|
+
Animated,
|
|
10
|
+
BackHandler,
|
|
11
|
+
Platform,
|
|
12
|
+
} from 'react-native';
|
|
4
13
|
import { useEffect, useState, useRef } from 'react';
|
|
5
14
|
import useStore from '../../store';
|
|
6
15
|
import { IDialogDown } from '../../models';
|
|
@@ -8,7 +17,7 @@ import { IDialogDown } from '../../models';
|
|
|
8
17
|
// Sistema simple de prioridades global
|
|
9
18
|
class PriorityManager {
|
|
10
19
|
private static instance: PriorityManager;
|
|
11
|
-
private currentDialog: { id: string; priority: number; onDismiss
|
|
20
|
+
private currentDialog: { id: string; priority: number; onDismiss?: () => void } | null = null;
|
|
12
21
|
private readonly listeners: Set<() => void> = new Set();
|
|
13
22
|
|
|
14
23
|
static getInstance(): PriorityManager {
|
|
@@ -27,10 +36,10 @@ class PriorityManager {
|
|
|
27
36
|
this.listeners.forEach((listener) => listener());
|
|
28
37
|
}
|
|
29
38
|
|
|
30
|
-
showDialog(id: string, priority: number, onDismiss
|
|
39
|
+
showDialog(id: string, priority: number, onDismiss?: () => void) {
|
|
31
40
|
// Si hay un diálogo actual y el nuevo tiene mayor prioridad, cerrar el actual
|
|
32
41
|
if (this.currentDialog && priority > this.currentDialog.priority) {
|
|
33
|
-
this.currentDialog.onDismiss();
|
|
42
|
+
this.currentDialog.onDismiss?.();
|
|
34
43
|
this.currentDialog = null;
|
|
35
44
|
}
|
|
36
45
|
|
|
@@ -129,16 +138,38 @@ export const DialogDown = (props: IDialogDown & { priority?: 0 | 1 | 2 | 3 | 4 |
|
|
|
129
138
|
};
|
|
130
139
|
}, []);
|
|
131
140
|
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
if (Platform.OS === 'android' && !onDismiss && isVisible) {
|
|
143
|
+
const backHandler = BackHandler.addEventListener('hardwareBackPress', () => {
|
|
144
|
+
// Si no hay onDismiss, prevenir el cierre
|
|
145
|
+
return true;
|
|
146
|
+
});
|
|
147
|
+
return () => backHandler.remove();
|
|
148
|
+
}
|
|
149
|
+
}, [isVisible, onDismiss]);
|
|
150
|
+
|
|
132
151
|
const handleDismiss = () => {
|
|
133
152
|
priorityManager.current.hideDialog(dialogId);
|
|
134
|
-
onDismiss();
|
|
153
|
+
onDismiss?.();
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const handleRequestClose = () => {
|
|
157
|
+
if (onDismiss) {
|
|
158
|
+
handleDismiss();
|
|
159
|
+
}
|
|
160
|
+
// Si no hay onDismiss, no hacer nada - previene el cierre
|
|
135
161
|
};
|
|
136
162
|
|
|
137
163
|
// Solo renderizar si este diálogo es el actual
|
|
138
164
|
const isCurrentDialog = Boolean(isVisible && currentDialog && currentDialog.id === dialogId);
|
|
139
165
|
|
|
140
166
|
return (
|
|
141
|
-
<Modal
|
|
167
|
+
<Modal
|
|
168
|
+
visible={isCurrentDialog}
|
|
169
|
+
transparent={true}
|
|
170
|
+
animationType="none"
|
|
171
|
+
onRequestClose={handleRequestClose}
|
|
172
|
+
>
|
|
142
173
|
<TouchableWithoutFeedback onPress={handleDismissKeyboard}>
|
|
143
174
|
<View style={stylesDialog.modalBackground}>
|
|
144
175
|
<Animated.View
|
|
@@ -64,8 +64,19 @@ export const DialogExamples = () => {
|
|
|
64
64
|
setIsVisible2(true);
|
|
65
65
|
}}
|
|
66
66
|
/>
|
|
67
|
-
<DialogDown
|
|
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"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HelperText, TextInput, Text } from 'react-native-paper';
|
|
2
2
|
import { getStyleInput } from '../../../assets/styles/elements/inputs';
|
|
3
|
-
import { useState
|
|
3
|
+
import { useState } from 'react';
|
|
4
4
|
import { View } from 'react-native';
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import useStore from '../../store';
|
|
@@ -43,64 +43,25 @@ export const Input = (props: IInputText) => {
|
|
|
43
43
|
const patternNumber = /^[0-9]*$/;
|
|
44
44
|
const patternAlphanumeric = /^[a-zA-Z0-9]*$/;
|
|
45
45
|
const patternLettersWithAccentsAndSpaces = /^[a-zA-ZáéíóúÁÉÍÓÚñÑ\s]*$/;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
// Solo si el usuario no está escribiendo
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
if (!isUserTypingRef.current && stringValue !== lastPropValueRef.current) {
|
|
60
|
-
lastPropValueRef.current = stringValue;
|
|
61
|
-
setLocalValue(stringValue);
|
|
46
|
+
const onChangeText = (text: string) => {
|
|
47
|
+
onChange(text);
|
|
48
|
+
setErrorRequired(false);
|
|
49
|
+
if (type === 'number' && !patternNumber.test(text)) {
|
|
50
|
+
onInvalid && onInvalid();
|
|
51
|
+
} else if (type === 'alphanumeric' && !patternAlphanumeric.test(text)) {
|
|
52
|
+
onInvalid && onInvalid();
|
|
53
|
+
} else if (type === 'text' && !patternLettersWithAccentsAndSpaces.test(text)) {
|
|
54
|
+
onInvalid && onInvalid();
|
|
55
|
+
} else if (pattern && !pattern.test(text)) {
|
|
56
|
+
onInvalid && onInvalid();
|
|
62
57
|
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const onChangeText = useCallback(
|
|
66
|
-
(text: string) => {
|
|
67
|
-
// Asegurar que el texto sea una cadena
|
|
68
|
-
const cleanText = typeof text === 'string' ? text : String(text);
|
|
69
|
-
|
|
70
|
-
// Marcar que el usuario está escribiendo
|
|
71
|
-
isUserTypingRef.current = true;
|
|
72
|
-
|
|
73
|
-
// Actualizar el estado local inmediatamente
|
|
74
|
-
setLocalValue(cleanText);
|
|
75
|
-
lastPropValueRef.current = cleanText;
|
|
76
|
-
|
|
77
|
-
// Pasar el texto directamente al onChange
|
|
78
|
-
onChange(cleanText);
|
|
79
|
-
|
|
80
|
-
// Resetear el flag después de un breve delay
|
|
81
|
-
setTimeout(() => {
|
|
82
|
-
isUserTypingRef.current = false;
|
|
83
|
-
}, 50);
|
|
84
|
-
|
|
85
|
-
setErrorRequired(false);
|
|
86
|
-
if (type === 'number' && !patternNumber.test(cleanText)) {
|
|
87
|
-
onInvalid && onInvalid();
|
|
88
|
-
} else if (type === 'alphanumeric' && !patternAlphanumeric.test(cleanText)) {
|
|
89
|
-
onInvalid && onInvalid();
|
|
90
|
-
} else if (type === 'text' && !patternLettersWithAccentsAndSpaces.test(cleanText)) {
|
|
91
|
-
onInvalid && onInvalid();
|
|
92
|
-
} else if (pattern && !pattern.test(cleanText)) {
|
|
93
|
-
onInvalid && onInvalid();
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
[onChange, type, pattern, onInvalid]
|
|
97
|
-
);
|
|
58
|
+
};
|
|
98
59
|
return (
|
|
99
60
|
<View>
|
|
100
61
|
<TextInput
|
|
101
|
-
label={!isFocus && placeholder &&
|
|
62
|
+
label={!isFocus && placeholder && value?.trim() === '' ? placeholder : label}
|
|
102
63
|
mode={mode ?? 'flat'}
|
|
103
|
-
value={
|
|
64
|
+
value={value}
|
|
104
65
|
onChangeText={onChangeText}
|
|
105
66
|
maxLength={maxLength}
|
|
106
67
|
selectionColor={
|
|
@@ -134,7 +95,7 @@ export const Input = (props: IInputText) => {
|
|
|
134
95
|
isFocus && isValid && !errorRequired && { backgroundColor: 'transparent' },
|
|
135
96
|
style ?? [],
|
|
136
97
|
]}
|
|
137
|
-
contentStyle={[styleInput['input-txt'], contentStyle ??
|
|
98
|
+
contentStyle={[styleInput['input-txt'], contentStyle ?? {}]}
|
|
138
99
|
underlineColor={
|
|
139
100
|
underlineColor
|
|
140
101
|
? underlineColor
|
|
@@ -145,7 +106,7 @@ export const Input = (props: IInputText) => {
|
|
|
145
106
|
activeUnderlineColor={
|
|
146
107
|
activeUnderlineColor
|
|
147
108
|
? activeUnderlineColor
|
|
148
|
-
: !isValid && value
|
|
109
|
+
: !isValid && value?.trim() !== ''
|
|
149
110
|
? styleInput['input-text--activeUnderline'].color
|
|
150
111
|
: errorRequired
|
|
151
112
|
? styleInput['input-txt-error'].color
|
|
@@ -153,14 +114,9 @@ export const Input = (props: IInputText) => {
|
|
|
153
114
|
}
|
|
154
115
|
underlineStyle={{ height: isFocus ? 1.5 : 2 }}
|
|
155
116
|
keyboardType={type === 'number' ? 'numeric' : 'default'}
|
|
156
|
-
autoCorrect={false}
|
|
157
|
-
autoCapitalize="none"
|
|
158
|
-
autoComplete="off"
|
|
159
|
-
textContentType="none"
|
|
160
|
-
spellCheck={false}
|
|
161
117
|
right={icon && <TextInput.Icon color={theme.colors.icon} icon={icon ?? ''} />}
|
|
162
|
-
|
|
163
|
-
|
|
118
|
+
readOnly={isDisabled || readonly}
|
|
119
|
+
selection={selection}
|
|
164
120
|
/>
|
|
165
121
|
{!isDisabled && (
|
|
166
122
|
<>
|