Skip to content

Commit 1b77d68

Browse files
committed
Initial refactor : split code into functions, add types
1 parent 7e2fa05 commit 1b77d68

File tree

2 files changed

+168
-124
lines changed

2 files changed

+168
-124
lines changed

src/index.tsx

Lines changed: 46 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,18 @@ import {
1919
TouchableWithoutFeedback,
2020
LayoutChangeEvent,
2121
} from 'react-native';
22-
import Animated, { EasingNode, timing, interpolateColors } from 'react-native-reanimated';
22+
import Animated, {
23+
EasingNode,
24+
timing,
25+
interpolateColors,
26+
} from 'react-native-reanimated';
2327
import { styles } from './styles';
2428

2529
import makeVisibleWhite from './assets/make_visible_white.png';
2630
import makeInvisibleWhite from './assets/make_invisible_white.png';
2731
import makeVisibleBlack from './assets/make_visible_black.png';
2832
import makeInvisibleBlack from './assets/make_invisible_black.png';
33+
import { getValueFromCurrencyMask, getValueFromNonCurrencyMask } from './utils';
2934

3035
export interface Props extends TextInputProps {
3136
/** Style to the container of whole component */
@@ -255,23 +260,23 @@ const FloatingLabelInput: React.ForwardRefRenderFunction<InputRef, Props> = (
255260
);
256261

257262
useEffect(() => {
258-
if (isFocused === undefined) {
259-
if (value !== '' || isFocusedState) {
260-
setIsFocused(true);
261-
} else if (value === '' || value === null) {
262-
setIsFocused(false);
263-
}
263+
if (isFocused === undefined) {
264+
if (value !== '' || isFocusedState) {
265+
setIsFocused(true);
266+
} else if (value === '' || value === null) {
267+
setIsFocused(false);
264268
}
269+
}
265270
}, [value]);
266271

267272
useEffect(() => {
268-
if (isFocused !== undefined) {
269-
if (value !== '' || isFocused) {
270-
setIsFocused(true);
271-
} else {
272-
setIsFocused(false);
273-
}
273+
if (isFocused !== undefined) {
274+
if (value !== '' || isFocused) {
275+
setIsFocused(true);
276+
} else {
277+
setIsFocused(false);
274278
}
279+
}
275280
}, [isFocused, value]);
276281

277282
useEffect(() => {
@@ -287,7 +292,7 @@ const FloatingLabelInput: React.ForwardRefRenderFunction<InputRef, Props> = (
287292
}
288293
} else {
289294
animateBlur();
290-
}
295+
}
291296
}, [isFocusedState]);
292297

293298
useImperativeHandle(ref, () => ({
@@ -298,7 +303,7 @@ const FloatingLabelInput: React.ForwardRefRenderFunction<InputRef, Props> = (
298303
inputRef.current.blur();
299304
},
300305
}));
301-
306+
302307
useEffect(() => {
303308
if (
304309
!staticLabel &&
@@ -343,13 +348,12 @@ const FloatingLabelInput: React.ForwardRefRenderFunction<InputRef, Props> = (
343348
easing: EasingNode.linear,
344349
}),
345350
]).start();
346-
}else if(staticLabel &&
347-
isFocusedState){
348-
Animated.timing(fontColorAnimated, {
349-
toValue: 1,
350-
duration: animationDuration ? animationDuration : 300,
351-
easing: EasingNode.linear,
352-
}).start();
351+
} else if (staticLabel && isFocusedState) {
352+
Animated.timing(fontColorAnimated, {
353+
toValue: 1,
354+
duration: animationDuration ? animationDuration : 300,
355+
easing: EasingNode.linear,
356+
}).start();
353357
}
354358
}, [halfTop]);
355359

@@ -393,7 +397,7 @@ const FloatingLabelInput: React.ForwardRefRenderFunction<InputRef, Props> = (
393397
easing: EasingNode.linear,
394398
}),
395399
]).start();
396-
}else{
400+
} else {
397401
Animated.timing(fontColorAnimated, {
398402
toValue: 1,
399403
duration: animationDuration ? animationDuration : 300,
@@ -435,7 +439,7 @@ const FloatingLabelInput: React.ForwardRefRenderFunction<InputRef, Props> = (
435439
easing: EasingNode.linear,
436440
}),
437441
]).start();
438-
}else{
442+
} else {
439443
Animated.timing(fontColorAnimated, {
440444
toValue: 0,
441445
duration: animationDuration ? animationDuration : 300,
@@ -494,7 +498,6 @@ const FloatingLabelInput: React.ForwardRefRenderFunction<InputRef, Props> = (
494498
? customShowPasswordImage || makeVisibleWhite
495499
: customHidePasswordImage || makeInvisibleWhite;
496500

497-
498501
const style: TextStyle = {
499502
...setGlobalStyles?.labelStyles,
500503
...labelStyles,
@@ -508,7 +511,10 @@ const FloatingLabelInput: React.ForwardRefRenderFunction<InputRef, Props> = (
508511
: customLabelStyles.fontSizeFocused,
509512
color: interpolateColors(fontColorAnimated, {
510513
inputRange: [0, 1],
511-
outputColorRange: [customLabelStyles.colorBlurred,customLabelStyles.colorFocused]
514+
outputColorRange: [
515+
customLabelStyles.colorBlurred,
516+
customLabelStyles.colorFocused,
517+
],
512518
}),
513519
alignSelf: 'center',
514520
position: 'absolute',
@@ -577,108 +583,24 @@ const FloatingLabelInput: React.ForwardRefRenderFunction<InputRef, Props> = (
577583
...showCountdownStyles,
578584
};
579585

580-
function onChangeTextCallback(val: string) {
581-
if (maskType !== undefined || mask !== undefined) {
582-
if (maskType !== 'currency' && mask !== undefined) {
583-
let unmasked = val.replace(/[^0-9A-Za-z]/g, '');
584-
585-
// pegar as posições dos caracteres especiais.
586-
let positions: number[] = [];
587-
for (let i = 0; i < mask.length; i++) {
588-
if (mask[i].match(/[^0-9A-Za-z]/)) {
589-
positions.push(i);
590-
}
591-
}
586+
function onChangeTextCallback(val: string): void | undefined {
587+
if (onChangeText === undefined) return undefined;
592588

593-
let newValue = '';
594-
let offset = 0;
595-
for (let j = 0; j < unmasked.length; j++) {
596-
// adicionar caracteres especiais
597-
while (mask[j + offset]?.match(/[^0-9A-Za-z]/)) {
598-
newValue += mask[j + offset];
599-
offset++;
600-
}
601-
newValue += unmasked[j];
602-
}
589+
if (maskType === undefined && mask === undefined) return onChangeText(val);
603590

604-
return onChangeText ? onChangeText(newValue) : false;
605-
}
606-
if (maskType === 'currency') {
607-
let divider = '';
608-
let decimal = '';
609-
if (currencyDivider === ',') {
610-
divider = ',';
611-
decimal = '.';
612-
} else {
613-
divider = '.';
614-
decimal = ',';
615-
}
616-
if (value !== undefined && value.length < val.length) {
617-
if (val.includes(decimal)) {
618-
let intVal = val.split(decimal)[0].replace(/[,.]/g, '');
619-
let decimalValue = val.split(decimal)[1];
620-
if (intVal.length > 3) {
621-
let arr: string[] = [];
622-
for (let i = 0; i < intVal.length; i += 3) {
623-
arr.push(
624-
intVal
625-
.split('')
626-
.splice(intVal.length - i, 3)
627-
.join(''),
628-
);
629-
}
591+
if (maskType !== 'currency' && mask !== undefined) {
592+
const newValue = getValueFromNonCurrencyMask({ value: val, mask });
593+
return onChangeText(newValue);
594+
}
630595

631-
arr = arr.reverse();
632-
arr.pop();
633-
let initial = arr.join('');
634-
if (intVal.includes(initial)) {
635-
intVal = intVal.replace(initial, '');
636-
}
637-
intVal = intVal + divider + arr.join(divider);
638-
}
639-
640-
val = intVal + decimal + decimalValue;
641-
642-
let decimalPlaces: number =
643-
maxDecimalPlaces !== undefined ? maxDecimalPlaces : 2;
644-
645-
if (
646-
val.split(decimal)[1] !== undefined &&
647-
value.split(decimal)[1] !== undefined &&
648-
val.split(decimal)[1].length > value.split(decimal)[1].length &&
649-
value.split(decimal)[1].length === decimalPlaces
650-
) {
651-
return;
652-
}
653-
if (val.split(decimal)[1].length > decimalPlaces) {
654-
val = val.slice(0, val.length - 1);
655-
}
656-
} else if (val.length > 3) {
657-
let arr: string[] = [];
658-
let unmasked = val.replace(/[,.]/g, '');
659-
for (let i = 0; i < unmasked.length; i += 3) {
660-
arr.push(
661-
unmasked
662-
.split('')
663-
.splice(unmasked.length - i, 3)
664-
.join(''),
665-
);
666-
}
667-
668-
arr = arr.reverse();
669-
arr.pop();
670-
let initial = arr.join('');
671-
if (unmasked.includes(initial)) {
672-
unmasked = unmasked.replace(initial, '');
673-
}
674-
val = unmasked + divider + arr.join(divider);
675-
}
676-
}
677-
return onChangeText ? onChangeText(val) : false;
678-
}
679-
return onChangeText ? onChangeText(val) : false;
596+
if (maskType === 'currency') {
597+
const newValue = getValueFromCurrencyMask({
598+
value: val,
599+
currencyDivider,
600+
maxDecimalPlaces,
601+
});
602+
return onChangeText(newValue);
680603
}
681-
return onChangeText ? onChangeText(val) : false;
682604
}
683605

684606
function onLayout(event: LayoutChangeEvent) {

src/utils.tsx

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
type MaskType = 'currency' | 'phone' | 'date' | 'card';
2+
type Mask = string;
3+
type CurrencyDivider = ',' | '.';
4+
5+
type CurrencyMaskTypeArgs = {
6+
value: string;
7+
newValue: string;
8+
currencyDivider: CurrencyDivider | undefined;
9+
maxDecimalPlaces: number | undefined;
10+
};
11+
12+
type NonCurrencyMaskTypeArgs = {
13+
value: string;
14+
mask: Mask;
15+
};
16+
17+
export function getValueFromNonCurrencyMask({
18+
value,
19+
mask,
20+
}: NonCurrencyMaskTypeArgs): string {
21+
let unmasked = value.replace(/[^0-9A-Za-z]/g, '');
22+
23+
// mark positions of special characters
24+
let positions: number[] = [];
25+
for (let i = 0; i < mask.length; i++) {
26+
if (mask[i].match(/[^0-9A-Za-z]/)) {
27+
positions.push(i);
28+
}
29+
}
30+
31+
let newValue = '';
32+
let offset = 0;
33+
for (let j = 0; j < unmasked.length; j++) {
34+
// add special characters
35+
while (mask[j + offset]?.match(/[^0-9A-Za-z]/)) {
36+
newValue += mask[j + offset];
37+
offset++;
38+
}
39+
newValue += unmasked[j];
40+
}
41+
42+
return newValue;
43+
}
44+
45+
export function getValueFromCurrencyMask({
46+
value,
47+
newValue,
48+
currencyDivider,
49+
maxDecimalPlaces,
50+
}: CurrencyMaskTypeArgs): string {
51+
let divider = '';
52+
let decimal = '';
53+
if (currencyDivider === ',') {
54+
divider = ',';
55+
decimal = '.';
56+
} else {
57+
divider = '.';
58+
decimal = ',';
59+
}
60+
if (value !== undefined && value.length < newValue.length) {
61+
if (newValue.includes(decimal)) {
62+
let intVal = newValue.split(decimal)[0].replace(/[,.]/g, '');
63+
let decimalValue = newValue.split(decimal)[1];
64+
if (intVal.length > 3) {
65+
let arr: string[] = [];
66+
for (let i = 0; i < intVal.length; i += 3) {
67+
arr.push(
68+
intVal
69+
.split('')
70+
.splice(intVal.length - i, 3)
71+
.join(''),
72+
);
73+
}
74+
75+
arr = arr.reverse();
76+
arr.pop();
77+
let initial = arr.join('');
78+
if (intVal.includes(initial)) {
79+
intVal = intVal.replace(initial, '');
80+
}
81+
intVal = intVal + divider + arr.join(divider);
82+
}
83+
84+
newValue = intVal + decimal + decimalValue;
85+
86+
let decimalPlaces: number =
87+
maxDecimalPlaces !== undefined ? maxDecimalPlaces : 2;
88+
89+
if (
90+
newValue.split(decimal)[1] !== undefined &&
91+
value.split(decimal)[1] !== undefined &&
92+
newValue.split(decimal)[1].length > value.split(decimal)[1].length &&
93+
value.split(decimal)[1].length === decimalPlaces
94+
) {
95+
return '';
96+
}
97+
if (newValue.split(decimal)[1].length > decimalPlaces) {
98+
newValue = newValue.slice(0, newValue.length - 1);
99+
}
100+
} else if (newValue.length > 3) {
101+
let arr: string[] = [];
102+
let unmasked = newValue.replace(/[,.]/g, '');
103+
for (let i = 0; i < unmasked.length; i += 3) {
104+
arr.push(
105+
unmasked
106+
.split('')
107+
.splice(unmasked.length - i, 3)
108+
.join(''),
109+
);
110+
}
111+
112+
arr = arr.reverse();
113+
arr.pop();
114+
let initial = arr.join('');
115+
if (unmasked.includes(initial)) {
116+
unmasked = unmasked.replace(initial, '');
117+
}
118+
newValue = unmasked + divider + arr.join(divider);
119+
}
120+
}
121+
return newValue;
122+
}

0 commit comments

Comments
 (0)