@dropi/react-native-design-system 0.3.9 → 0.3.11
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/lib/molecules/InputField/Input.d.ts +28 -6
- package/lib/molecules/InputField/Input.js +6 -6
- package/lib/molecules/InputField/NumberInput.d.ts +19 -0
- package/lib/molecules/InputField/NumberInput.js +88 -0
- package/lib/molecules/InputField/TextInput.d.ts +15 -0
- package/lib/molecules/InputField/TextInput.js +49 -0
- package/lib/molecules/InputField/index.d.ts +2 -0
- package/lib/molecules/InputField/index.js +22 -0
- package/lib/molecules/Toasts/ToastProvider/ToastProvider.js +82 -46
- package/package.json +1 -1
|
@@ -2,25 +2,47 @@ type InputType = "text" | "number" | "email" | "password";
|
|
|
2
2
|
type InputFactoryProps = {
|
|
3
3
|
type: InputType;
|
|
4
4
|
};
|
|
5
|
-
export declare const Input: ({ type, ...props }: InputFactoryProps) =>
|
|
6
|
-
type?: import("react-native").KeyboardTypeOptions;
|
|
5
|
+
export declare const Input: ({ type, ...props }: InputFactoryProps) => (({ preIcon, helper, tooltip, value, onChange, hasError, errorMessage, readOnly, }: {
|
|
7
6
|
preIcon?: import("dropi-lib-icons").IconName;
|
|
7
|
+
helper?: string;
|
|
8
|
+
tooltip?: string;
|
|
9
|
+
value: string;
|
|
10
|
+
onChange: (value: string) => void;
|
|
11
|
+
hasError: boolean;
|
|
12
|
+
errorMessage?: string;
|
|
13
|
+
readOnly: boolean;
|
|
14
|
+
}) => import("react/jsx-runtime").JSX.Element) | import("react").ForwardRefExoticComponent<import("react-native").TextInputProps & {
|
|
15
|
+
preIcon?: import("dropi-lib-icons").IconName;
|
|
16
|
+
helper?: string;
|
|
17
|
+
tooltip?: string;
|
|
18
|
+
value: string;
|
|
19
|
+
onChangeFunction: (value: string) => void;
|
|
20
|
+
hasError: boolean;
|
|
21
|
+
errorMessage?: string;
|
|
22
|
+
} & import("react").RefAttributes<import("react-native").TextInput>> | (({ label, preIcon, helper, tooltip, placeholder, value, onChange, hasError, errorMessage, readOnly, }: {
|
|
8
23
|
label?: string;
|
|
24
|
+
preIcon?: import("dropi-lib-icons").IconName;
|
|
9
25
|
helper?: string;
|
|
10
|
-
placeholder?: string;
|
|
11
26
|
tooltip?: string;
|
|
27
|
+
placeholder?: string;
|
|
12
28
|
value: string;
|
|
29
|
+
onChange: (value: string) => void;
|
|
13
30
|
hasError: boolean;
|
|
14
31
|
errorMessage?: string;
|
|
15
|
-
|
|
16
|
-
}
|
|
32
|
+
readOnly?: boolean;
|
|
33
|
+
}) => import("react/jsx-runtime").JSX.Element) | (({ label, preIcon, helper, tooltip, placeholder, value, onChange, hasError, errorMessage, readOnly, allowDecimals, minValue, maxValue, }: {
|
|
34
|
+
label?: string;
|
|
17
35
|
preIcon?: import("dropi-lib-icons").IconName;
|
|
18
36
|
helper?: string;
|
|
19
37
|
tooltip?: string;
|
|
38
|
+
placeholder?: string;
|
|
20
39
|
value: string;
|
|
21
40
|
onChange: (value: string) => void;
|
|
22
41
|
hasError: boolean;
|
|
23
42
|
errorMessage?: string;
|
|
24
|
-
readOnly
|
|
43
|
+
readOnly?: boolean;
|
|
44
|
+
allowDecimals?: boolean;
|
|
45
|
+
minValue?: number;
|
|
46
|
+
maxValue?: number;
|
|
25
47
|
}) => import("react/jsx-runtime").JSX.Element);
|
|
26
48
|
export {};
|
|
@@ -4,15 +4,15 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.Input = void 0;
|
|
7
|
-
var
|
|
7
|
+
var _TextInput = require("./TextInput");
|
|
8
|
+
var _NumberInput = require("./NumberInput");
|
|
8
9
|
var _EmailInput = require("./EmailInput");
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
var _PasswordInput = require("./PasswordInput");
|
|
11
11
|
const InputComponents = {
|
|
12
|
-
text:
|
|
13
|
-
number:
|
|
12
|
+
text: _TextInput.TextInput,
|
|
13
|
+
number: _NumberInput.NumberInput,
|
|
14
14
|
email: _EmailInput.EmailInput,
|
|
15
|
-
password:
|
|
15
|
+
password: _PasswordInput.PasswordInput
|
|
16
16
|
};
|
|
17
17
|
const Input = ({
|
|
18
18
|
type,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { IconName } from "dropi-lib-icons";
|
|
2
|
+
type NumberInputProps = {
|
|
3
|
+
label?: string;
|
|
4
|
+
preIcon?: IconName;
|
|
5
|
+
helper?: string;
|
|
6
|
+
tooltip?: string;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
value: string;
|
|
9
|
+
onChange: (value: string) => void;
|
|
10
|
+
hasError: boolean;
|
|
11
|
+
errorMessage?: string;
|
|
12
|
+
readOnly?: boolean;
|
|
13
|
+
allowDecimals?: boolean;
|
|
14
|
+
minValue?: number;
|
|
15
|
+
maxValue?: number;
|
|
16
|
+
};
|
|
17
|
+
export declare const validateNumber: (value: string, allowDecimals?: boolean, minValue?: number, maxValue?: number) => boolean;
|
|
18
|
+
export declare const NumberInput: ({ label, preIcon, helper, tooltip, placeholder, value, onChange, hasError, errorMessage, readOnly, allowDecimals, minValue, maxValue, }: NumberInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.validateNumber = exports.NumberInput = void 0;
|
|
7
|
+
var _BaseInput = require("./BaseInput");
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
10
|
+
const validateNumber = (value, allowDecimals = true, minValue, maxValue) => {
|
|
11
|
+
if (value === "" || value === "-") return true;
|
|
12
|
+
const numberRegex = allowDecimals ? /^-?\d+\.?\d*$/ : /^-?\d+$/;
|
|
13
|
+
if (!numberRegex.test(value)) return false;
|
|
14
|
+
const numValue = parseFloat(value);
|
|
15
|
+
if (minValue !== undefined && numValue < minValue) return false;
|
|
16
|
+
if (maxValue !== undefined && numValue > maxValue) return false;
|
|
17
|
+
return true;
|
|
18
|
+
};
|
|
19
|
+
exports.validateNumber = validateNumber;
|
|
20
|
+
const NumberInput = ({
|
|
21
|
+
label,
|
|
22
|
+
preIcon,
|
|
23
|
+
helper,
|
|
24
|
+
tooltip,
|
|
25
|
+
placeholder,
|
|
26
|
+
value,
|
|
27
|
+
onChange,
|
|
28
|
+
hasError,
|
|
29
|
+
errorMessage,
|
|
30
|
+
readOnly = false,
|
|
31
|
+
allowDecimals = true,
|
|
32
|
+
minValue,
|
|
33
|
+
maxValue
|
|
34
|
+
}) => {
|
|
35
|
+
const [focus, setFocus] = (0, _react.useState)(false);
|
|
36
|
+
const [invalidNumber, setInvalidNumber] = (0, _react.useState)(false);
|
|
37
|
+
const [wasVisited, setWasVisited] = (0, _react.useState)(false);
|
|
38
|
+
const onFocus = () => {
|
|
39
|
+
setFocus(true);
|
|
40
|
+
};
|
|
41
|
+
const onBlur = () => {
|
|
42
|
+
setFocus(false);
|
|
43
|
+
if (!wasVisited) {
|
|
44
|
+
setWasVisited(true);
|
|
45
|
+
if (value && !validateNumber(value, allowDecimals, minValue, maxValue)) {
|
|
46
|
+
setInvalidNumber(true);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const getErrorMessage = () => {
|
|
51
|
+
if (hasError) {
|
|
52
|
+
return errorMessage;
|
|
53
|
+
}
|
|
54
|
+
if (invalidNumber) {
|
|
55
|
+
if (!allowDecimals) {
|
|
56
|
+
return "Ingresa un número entero válido";
|
|
57
|
+
}
|
|
58
|
+
return "Ingresa un número válido";
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_BaseInput.BaseInput, {
|
|
62
|
+
type: "decimal-pad",
|
|
63
|
+
label: label,
|
|
64
|
+
placeholder: placeholder || "Ingresa un número",
|
|
65
|
+
value: value,
|
|
66
|
+
preIcon: preIcon,
|
|
67
|
+
helper: helper,
|
|
68
|
+
tooltip: tooltip,
|
|
69
|
+
onChangeText: text => {
|
|
70
|
+
onChange(text);
|
|
71
|
+
if (wasVisited) {
|
|
72
|
+
if (text === "" || validateNumber(text, allowDecimals, minValue, maxValue)) {
|
|
73
|
+
setInvalidNumber(false);
|
|
74
|
+
} else {
|
|
75
|
+
setInvalidNumber(true);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
hasError: hasError || invalidNumber,
|
|
80
|
+
errorMessage: getErrorMessage(),
|
|
81
|
+
autoCorrect: false,
|
|
82
|
+
readOnly: readOnly,
|
|
83
|
+
onBlur: onBlur,
|
|
84
|
+
onFocus: onFocus,
|
|
85
|
+
isFocus: focus
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
exports.NumberInput = NumberInput;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { IconName } from "dropi-lib-icons";
|
|
2
|
+
type TextInputProps = {
|
|
3
|
+
label?: string;
|
|
4
|
+
preIcon?: IconName;
|
|
5
|
+
helper?: string;
|
|
6
|
+
tooltip?: string;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
value: string;
|
|
9
|
+
onChange: (value: string) => void;
|
|
10
|
+
hasError: boolean;
|
|
11
|
+
errorMessage?: string;
|
|
12
|
+
readOnly?: boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare const TextInput: ({ label, preIcon, helper, tooltip, placeholder, value, onChange, hasError, errorMessage, readOnly, }: TextInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.TextInput = void 0;
|
|
7
|
+
var _BaseInput = require("./BaseInput");
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
10
|
+
const TextInput = ({
|
|
11
|
+
label,
|
|
12
|
+
preIcon,
|
|
13
|
+
helper,
|
|
14
|
+
tooltip,
|
|
15
|
+
placeholder,
|
|
16
|
+
value,
|
|
17
|
+
onChange,
|
|
18
|
+
hasError,
|
|
19
|
+
errorMessage,
|
|
20
|
+
readOnly = false
|
|
21
|
+
}) => {
|
|
22
|
+
const [focus, setFocus] = (0, _react.useState)(false);
|
|
23
|
+
const onFocus = () => {
|
|
24
|
+
setFocus(true);
|
|
25
|
+
};
|
|
26
|
+
const onBlur = () => {
|
|
27
|
+
setFocus(false);
|
|
28
|
+
};
|
|
29
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_BaseInput.BaseInput, {
|
|
30
|
+
type: "default",
|
|
31
|
+
label: label,
|
|
32
|
+
placeholder: placeholder || "Ingresa texto",
|
|
33
|
+
value: value,
|
|
34
|
+
preIcon: preIcon,
|
|
35
|
+
helper: helper,
|
|
36
|
+
tooltip: tooltip,
|
|
37
|
+
onChangeText: text => {
|
|
38
|
+
onChange(text);
|
|
39
|
+
},
|
|
40
|
+
hasError: hasError,
|
|
41
|
+
errorMessage: errorMessage,
|
|
42
|
+
autoCorrect: false,
|
|
43
|
+
readOnly: readOnly,
|
|
44
|
+
onBlur: onBlur,
|
|
45
|
+
onFocus: onFocus,
|
|
46
|
+
isFocus: focus
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
exports.TextInput = TextInput;
|
|
@@ -35,4 +35,26 @@ Object.keys(_BaseInput).forEach(function (key) {
|
|
|
35
35
|
return _BaseInput[key];
|
|
36
36
|
}
|
|
37
37
|
});
|
|
38
|
+
});
|
|
39
|
+
var _TextInput = require("./TextInput");
|
|
40
|
+
Object.keys(_TextInput).forEach(function (key) {
|
|
41
|
+
if (key === "default" || key === "__esModule") return;
|
|
42
|
+
if (key in exports && exports[key] === _TextInput[key]) return;
|
|
43
|
+
Object.defineProperty(exports, key, {
|
|
44
|
+
enumerable: true,
|
|
45
|
+
get: function () {
|
|
46
|
+
return _TextInput[key];
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
var _NumberInput = require("./NumberInput");
|
|
51
|
+
Object.keys(_NumberInput).forEach(function (key) {
|
|
52
|
+
if (key === "default" || key === "__esModule") return;
|
|
53
|
+
if (key in exports && exports[key] === _NumberInput[key]) return;
|
|
54
|
+
Object.defineProperty(exports, key, {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get: function () {
|
|
57
|
+
return _NumberInput[key];
|
|
58
|
+
}
|
|
59
|
+
});
|
|
38
60
|
});
|
|
@@ -22,6 +22,10 @@ const ToastProvider = ({
|
|
|
22
22
|
const timeoutRef = (0, _react.useRef)(null);
|
|
23
23
|
const animationRef = (0, _react.useRef)(null);
|
|
24
24
|
const toastIdCounter = (0, _react.useRef)(0);
|
|
25
|
+
const isAnimatingRef = (0, _react.useRef)(false);
|
|
26
|
+
const processQueueRef = (0, _react.useRef)(null);
|
|
27
|
+
const animateInRef = (0, _react.useRef)(null);
|
|
28
|
+
const animateOutRef = (0, _react.useRef)(null);
|
|
25
29
|
|
|
26
30
|
// Cleanup timers on unmount
|
|
27
31
|
(0, _react.useEffect)(() => {
|
|
@@ -35,33 +39,31 @@ const ToastProvider = ({
|
|
|
35
39
|
};
|
|
36
40
|
}, []);
|
|
37
41
|
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
slideAnim.setValue(-200); // Reset to initial position
|
|
42
|
+
// Keep isAnimatingRef in sync
|
|
43
|
+
(0, _react.useEffect)(() => {
|
|
44
|
+
isAnimatingRef.current = isAnimating;
|
|
45
|
+
}, [isAnimating]);
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}, [slideAnim, isAnimating]);
|
|
47
|
+
// Process the next toast in the queue
|
|
48
|
+
const processQueue = (0, _react.useCallback)(() => {
|
|
49
|
+
setTimeout(() => {
|
|
50
|
+
setQueue(prevQueue => {
|
|
51
|
+
if (prevQueue.length === 0) return prevQueue;
|
|
52
|
+
const [nextToast, ...remainingQueue] = prevQueue;
|
|
53
|
+
setCurrentToast(nextToast);
|
|
54
|
+
return remainingQueue;
|
|
55
|
+
});
|
|
56
|
+
}, 0);
|
|
57
|
+
}, []);
|
|
58
|
+
|
|
59
|
+
// Keep processQueueRef updated
|
|
60
|
+
(0, _react.useEffect)(() => {
|
|
61
|
+
processQueueRef.current = processQueue;
|
|
62
|
+
}, [processQueue]);
|
|
61
63
|
|
|
62
|
-
// Animate out the toast
|
|
64
|
+
// Animate out the toast - stable with useRef
|
|
63
65
|
const animateOut = (0, _react.useCallback)(callback => {
|
|
64
|
-
if (
|
|
66
|
+
if (animationRef.current) {
|
|
65
67
|
animationRef.current.stop();
|
|
66
68
|
}
|
|
67
69
|
setIsAnimating(true);
|
|
@@ -75,7 +77,6 @@ const ToastProvider = ({
|
|
|
75
77
|
}) => {
|
|
76
78
|
if (finished) {
|
|
77
79
|
setIsAnimating(false);
|
|
78
|
-
// Defer state updates to avoid useInsertionEffect error
|
|
79
80
|
requestAnimationFrame(() => {
|
|
80
81
|
setCurrentToast(null);
|
|
81
82
|
if (callback) {
|
|
@@ -84,22 +85,57 @@ const ToastProvider = ({
|
|
|
84
85
|
});
|
|
85
86
|
}
|
|
86
87
|
});
|
|
87
|
-
}, [slideAnim
|
|
88
|
+
}, [slideAnim]);
|
|
88
89
|
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
90
|
+
// Keep animateOutRef updated
|
|
91
|
+
(0, _react.useEffect)(() => {
|
|
92
|
+
animateOutRef.current = animateOut;
|
|
93
|
+
}, [animateOut]);
|
|
94
|
+
|
|
95
|
+
// Animate in the toast - stable with useRef
|
|
96
|
+
const animateIn = (0, _react.useCallback)(() => {
|
|
97
|
+
if (isAnimatingRef.current) return;
|
|
98
|
+
setIsAnimating(true);
|
|
99
|
+
slideAnim.setValue(-200);
|
|
100
|
+
animationRef.current = _reactNative.Animated.sequence([_reactNative.Animated.timing(slideAnim, {
|
|
101
|
+
toValue: _reactNative.Platform.OS === 'ios' ? 100 : 50 + _utils.statusBarHeight,
|
|
102
|
+
duration: 300,
|
|
103
|
+
useNativeDriver: true
|
|
104
|
+
}), _reactNative.Animated.timing(slideAnim, {
|
|
105
|
+
toValue: _reactNative.Platform.OS === 'ios' ? 80 : 30 + _utils.statusBarHeight,
|
|
106
|
+
duration: 120,
|
|
107
|
+
useNativeDriver: true
|
|
108
|
+
})]);
|
|
109
|
+
animationRef.current.start(({
|
|
110
|
+
finished
|
|
111
|
+
}) => {
|
|
112
|
+
if (finished) {
|
|
113
|
+
setIsAnimating(false);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}, [slideAnim]);
|
|
117
|
+
|
|
118
|
+
// Keep animateInRef updated
|
|
119
|
+
(0, _react.useEffect)(() => {
|
|
120
|
+
animateInRef.current = animateIn;
|
|
121
|
+
}, [animateIn]);
|
|
122
|
+
|
|
123
|
+
// Auto-process queue when currentToast is null and queue has items
|
|
124
|
+
(0, _react.useEffect)(() => {
|
|
125
|
+
if (!currentToast && !isAnimating && queue.length > 0) {
|
|
126
|
+
// Defer to avoid state update during render
|
|
127
|
+
setTimeout(() => {
|
|
128
|
+
setQueue(prevQueue => {
|
|
129
|
+
if (prevQueue.length === 0) return prevQueue;
|
|
130
|
+
const [nextToast, ...remainingQueue] = prevQueue;
|
|
131
|
+
setCurrentToast(nextToast);
|
|
132
|
+
return remainingQueue;
|
|
133
|
+
});
|
|
134
|
+
}, 0);
|
|
135
|
+
}
|
|
136
|
+
}, [currentToast, isAnimating, queue.length]);
|
|
101
137
|
|
|
102
|
-
// Handle auto-dismiss
|
|
138
|
+
// Handle auto-dismiss - only depends on currentToast
|
|
103
139
|
(0, _react.useEffect)(() => {
|
|
104
140
|
if (!currentToast) return;
|
|
105
141
|
|
|
@@ -109,14 +145,14 @@ const ToastProvider = ({
|
|
|
109
145
|
timeoutRef.current = null;
|
|
110
146
|
}
|
|
111
147
|
|
|
112
|
-
// Animate in
|
|
113
|
-
|
|
148
|
+
// Animate in using ref
|
|
149
|
+
animateInRef.current?.();
|
|
114
150
|
|
|
115
151
|
// Set auto-dismiss if duration > 0
|
|
116
152
|
if (currentToast.duration && currentToast.duration > 0) {
|
|
117
153
|
timeoutRef.current = setTimeout(() => {
|
|
118
|
-
|
|
119
|
-
|
|
154
|
+
animateOutRef.current?.(() => {
|
|
155
|
+
processQueueRef.current?.();
|
|
120
156
|
});
|
|
121
157
|
}, currentToast.duration);
|
|
122
158
|
}
|
|
@@ -126,7 +162,7 @@ const ToastProvider = ({
|
|
|
126
162
|
timeoutRef.current = null;
|
|
127
163
|
}
|
|
128
164
|
};
|
|
129
|
-
}, [currentToast
|
|
165
|
+
}, [currentToast]); // Solo depende de currentToast para evitar bucle infinito
|
|
130
166
|
|
|
131
167
|
// Handle manual close
|
|
132
168
|
const handleClose = (0, _react.useCallback)(() => {
|
|
@@ -135,9 +171,9 @@ const ToastProvider = ({
|
|
|
135
171
|
timeoutRef.current = null;
|
|
136
172
|
}
|
|
137
173
|
animateOut(() => {
|
|
138
|
-
|
|
174
|
+
processQueueRef.current?.();
|
|
139
175
|
});
|
|
140
|
-
}, [animateOut
|
|
176
|
+
}, [animateOut]);
|
|
141
177
|
|
|
142
178
|
// Public API: showToast
|
|
143
179
|
const showToast = (0, _react.useCallback)(params => {
|