Skip to content

Commit a38bb3c

Browse files
committed
refactor: simplify theme handling and improve performance
- remove theme-related files and dependencies - inline color values in components - optimize hooks with useCallback and useMemo - simplify AnimatedCaret component - remove unnecessary theme-related props and styles
1 parent 7bc06ab commit a38bb3c

7 files changed

+83
-126
lines changed

src/components/animated-caret.tsx

+7-16
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,34 @@
1-
import { StyleSheet, Animated, useAnimatedValue } from 'react-native';
2-
import { useThemeColor } from '../theme/use-theme-color';
3-
import { theme } from '../theme/theme';
41
import { useEffect } from 'react';
2+
import { StyleSheet, Animated, useAnimatedValue } from 'react-native';
53

64
export function AnimatedCaret() {
7-
const backgroundColor = useThemeColor({
8-
light: theme.colorBlack,
9-
dark: theme.colorWhite,
10-
});
11-
const opacityValue = useAnimatedValue(0);
5+
const opacity = useAnimatedValue(0);
126

137
useEffect(() => {
148
Animated.loop(
159
Animated.sequence([
16-
Animated.timing(opacityValue, {
10+
Animated.timing(opacity, {
1711
toValue: 0,
1812
duration: 500,
1913
useNativeDriver: true,
2014
}),
21-
Animated.timing(opacityValue, {
15+
Animated.timing(opacity, {
2216
toValue: 1,
2317
duration: 500,
2418
useNativeDriver: true,
2519
}),
2620
])
2721
).start();
28-
}, [opacityValue]);
22+
}, [opacity]);
2923

30-
return (
31-
<Animated.View
32-
style={[styles.caret, { backgroundColor, opacity: opacityValue }]}
33-
/>
34-
);
24+
return <Animated.View style={[styles.caret, { opacity }]} />;
3525
}
3626

3727
const styles = StyleSheet.create({
3828
caret: {
3929
width: 2,
4030
height: 16,
4131
borderRadius: 16,
32+
backgroundColor: '#030712',
4233
},
4334
});

src/components/text-input-otp-separator.tsx

+1-14
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,11 @@
11
import { View, StyleSheet } from 'react-native';
2-
import { useThemeColor } from '../theme/use-theme-color';
3-
import { theme } from '../theme/theme';
42
import type { TextInputOTPSeparatorProps } from '../types';
53

64
export function TextInputOTPSeparator({
75
separatorStyles,
86
}: TextInputOTPSeparatorProps) {
9-
const backgroundColor = useThemeColor({
10-
light: theme.colorBlack,
11-
dark: theme.colorDarkGrey,
12-
});
13-
147
return (
15-
<View
16-
style={StyleSheet.flatten([
17-
styles.separator,
18-
{ backgroundColor },
19-
separatorStyles,
20-
])}
21-
/>
8+
<View style={StyleSheet.flatten([styles.separator, separatorStyles])} />
229
);
2310
}
2411

src/components/text-input-otp-slot.tsx

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
import { memo } from 'react';
22
import { Pressable, Text, StyleSheet } from 'react-native';
3+
import { AnimatedCaret } from './animated-caret';
34
import { useTextInputOTP } from '../hooks/use-text-input-otp';
5+
import { useSlotBorderStyles } from '../hooks/use-slot-border-styles';
6+
import { SLOT_HEIGHT, SLOT_WIDTH } from '../constants';
47
import type {
58
TextInputOTPSlotInternalProps,
69
TextInputOTPSlotProps,
710
} from '../types';
8-
import { useSlotBorderStyles } from '../hooks/use-slot-border-styles';
9-
import { useThemeColor } from '../theme/use-theme-color';
10-
import { theme } from '../theme/theme';
11-
import { AnimatedCaret } from './animated-caret';
12-
import { SLOT_HEIGHT, SLOT_WIDTH } from '../constants';
1311

1412
function TextInputOTPSlotComponent({
1513
index,
@@ -24,10 +22,6 @@ function TextInputOTPSlotComponent({
2422
const { code, currentIndex, handlePress } = useTextInputOTP();
2523
const isFocused = currentIndex === index;
2624
const borderStyles = useSlotBorderStyles({ isFocused, isFirst, isLast });
27-
const slotTextColor = useThemeColor({
28-
light: theme.colorBlack,
29-
dark: theme.colorWhite,
30-
});
3125

3226
return (
3327
<Pressable
@@ -43,7 +37,6 @@ function TextInputOTPSlotComponent({
4337
<Text
4438
style={StyleSheet.flatten([
4539
styles.slotText,
46-
{ color: slotTextColor },
4740
isFocused ? focusedSlotTextStyles : slotTextStyles,
4841
])}
4942
>
@@ -66,6 +59,7 @@ const styles = StyleSheet.create({
6659
alignItems: 'center',
6760
},
6861
slotText: {
62+
color: '#030712',
6963
fontSize: 14,
7064
fontWeight: 'bold',
7165
},

src/hooks/use-slot-border-styles.ts

+1-12
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,13 @@
1-
import { theme } from '../theme/theme';
2-
import { useThemeColor } from '../theme/use-theme-color';
31
import type { UseSlotBorderStylesProps } from '../types/text-input-otp-slot';
42

53
export function useSlotBorderStyles({
64
isFocused,
75
isFirst,
86
isLast,
97
}: UseSlotBorderStylesProps) {
10-
const blurredBorderColor = useThemeColor({
11-
light: theme.colorLightGrey,
12-
dark: theme.colorDarkGrey,
13-
});
14-
const focusedBorderColor = useThemeColor({
15-
light: theme.colorBlack,
16-
dark: theme.colorWhite,
17-
});
18-
198
return {
209
height: isFocused ? 54 : 50,
21-
borderColor: isFocused ? focusedBorderColor : blurredBorderColor,
10+
borderColor: isFocused ? '#030712' : '#E4E7EC',
2211
borderTopWidth: 2,
2312
borderBottomWidth: 2,
2413
borderLeftWidth: isFocused || isFirst ? 2 : 1,

src/hooks/use-text-input-otp.tsx

+70-55
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import {
22
createContext,
3+
useCallback,
34
useContext,
5+
useMemo,
46
useRef,
57
useState,
68
type PropsWithChildren,
@@ -38,61 +40,71 @@ export function TextInputOTPProvider({
3840
const [currentIndex, setCurrentIndex] = useState(autoFocus ? 0 : -1);
3941
const inputRef = useRef<TextInput>(null);
4042

41-
function updateCodeAtIndex(index: number, value: string) {
42-
const newCode = [...code];
43-
newCode[index] = value;
44-
setCode(newCode);
43+
const updateCodeAtIndex = useCallback(
44+
(index: number, value: string) => {
45+
const newCode = [...code];
46+
newCode[index] = value;
47+
setCode(newCode);
4548

46-
return newCode;
47-
}
49+
return newCode;
50+
},
51+
[code]
52+
);
4853

49-
function handleKeyPress(
50-
event: NativeSyntheticEvent<TextInputKeyPressEventData>
51-
) {
52-
const { key } = event.nativeEvent;
54+
const handleKeyPress = useCallback(
55+
(event: NativeSyntheticEvent<TextInputKeyPressEventData>) => {
56+
const { key } = event.nativeEvent;
5357

54-
if (key !== BACKSPACE_KEY) {
55-
return;
56-
}
58+
if (key !== BACKSPACE_KEY) {
59+
return;
60+
}
5761

58-
if (!code[currentIndex] && currentIndex > 0) {
59-
updateCodeAtIndex(currentIndex - 1, '');
60-
setCurrentIndex((prev) => prev - 1);
61-
return;
62-
}
62+
if (!code[currentIndex] && currentIndex > 0) {
63+
updateCodeAtIndex(currentIndex - 1, '');
64+
setCurrentIndex((prev) => prev - 1);
65+
return;
66+
}
6367

64-
updateCodeAtIndex(currentIndex, '');
65-
}
68+
updateCodeAtIndex(currentIndex, '');
69+
},
70+
[code, currentIndex, updateCodeAtIndex]
71+
);
6672

67-
function handleChangeText(text: string) {
68-
if (text.length > 1) {
69-
return;
70-
}
73+
const handleChangeText = useCallback(
74+
(text: string) => {
75+
if (text.length > 1) {
76+
return;
77+
}
7178

72-
const updatedCode = updateCodeAtIndex(currentIndex, text);
79+
const updatedCode = updateCodeAtIndex(currentIndex, text);
7380

74-
if (currentIndex < maxLength - 1) {
75-
setCurrentIndex((prev) => prev + 1);
76-
return;
77-
}
81+
if (currentIndex < maxLength - 1) {
82+
setCurrentIndex((prev) => prev + 1);
83+
return;
84+
}
7885

79-
const finalCode = [...updatedCode].join('');
86+
const finalCode = [...updatedCode].join('');
8087

81-
if (finalCode.length === maxLength) {
82-
onFilled?.(finalCode);
83-
}
84-
}
88+
if (finalCode.length === maxLength) {
89+
onFilled?.(finalCode);
90+
}
91+
},
92+
[currentIndex, maxLength, onFilled, updateCodeAtIndex]
93+
);
8594

8695
function handlePress(index: number) {
8796
setCurrentIndex(index);
8897
inputRef.current?.focus();
8998
}
9099

91-
function setValue(text: string) {
92-
const value = text.length > maxLength ? text.slice(0, maxLength) : text;
93-
setCode(Array.from(value));
94-
setCurrentIndex(maxLength - 1);
95-
}
100+
const setValue = useCallback(
101+
(text: string) => {
102+
const value = text.length > maxLength ? text.slice(0, maxLength) : text;
103+
setCode(Array.from(value));
104+
setCurrentIndex(maxLength - 1);
105+
},
106+
[maxLength]
107+
);
96108

97109
function focus() {
98110
inputRef.current?.focus();
@@ -102,26 +114,29 @@ export function TextInputOTPProvider({
102114
inputRef.current?.blur();
103115
}
104116

105-
function clear() {
117+
const clear = useCallback(() => {
106118
setCode(Array(maxLength).fill(''));
107119
setCurrentIndex(0);
108-
}
120+
}, [maxLength]);
121+
122+
const contextValue = useMemo(
123+
() => ({
124+
code,
125+
currentIndex,
126+
inputRef,
127+
handleKeyPress,
128+
handleChangeText,
129+
handlePress,
130+
setValue,
131+
focus,
132+
blur,
133+
clear,
134+
}),
135+
[clear, code, currentIndex, handleChangeText, handleKeyPress, setValue]
136+
);
109137

110138
return (
111-
<TextInputOTPContext.Provider
112-
value={{
113-
code,
114-
currentIndex,
115-
inputRef,
116-
handleKeyPress,
117-
handleChangeText,
118-
handlePress,
119-
setValue,
120-
focus,
121-
blur,
122-
clear,
123-
}}
124-
>
139+
<TextInputOTPContext.Provider value={contextValue}>
125140
{children}
126141
</TextInputOTPContext.Provider>
127142
);

src/theme/theme.ts

-12
This file was deleted.

src/theme/use-theme-color.ts

-7
This file was deleted.

0 commit comments

Comments
 (0)