import React, { useRef, useEffect, useState, useCallback } from 'react'; import { View, TextInput, Text, Pressable, ActivityIndicator, Animated, StyleSheet, } from 'react-native'; import { useTheme } from '../../theme/useTheme'; import type { SearchBarProps } from './SearchBar.types'; export const SearchBar: React.FC = ({ value, onChangeText, onClear, onSubmit, placeholder = 'Search...', loading = false, disabled = false, style, onFocus, onBlur, ...rest }) => { const theme = useTheme(); const [focused, setFocused] = useState(false); const borderAnim = useRef(new Animated.Value(0)).current; useEffect(() => { Animated.timing(borderAnim, { toValue: focused ? 1 : 0, duration: 200, useNativeDriver: false, }).start(); }, [focused, borderAnim]); const borderColor = borderAnim.interpolate({ inputRange: [0, 1], outputRange: [theme.colors.border, theme.colors.primary], }); const handleFocus = useCallback( (e: Parameters>[0]) => { setFocused(true); onFocus?.(e); }, [onFocus] ); const handleBlur = useCallback( (e: Parameters>[0]) => { setFocused(false); onBlur?.(e); }, [onBlur] ); const handleClear = useCallback(() => { onChangeText(''); onClear?.(); }, [onChangeText, onClear]); const handleSubmitEditing = useCallback(() => { onSubmit?.(); }, [onSubmit]); const showClear = value.length > 0 && !loading; return ( {'\u2315'} {loading && ( )} {showClear && !loading && ( )} ); }; const styles = StyleSheet.create({ container: { minHeight: 44, }, inner: { flexDirection: 'row', alignItems: 'center', }, icon: { fontSize: 18, marginRight: 10, }, input: { flex: 1, padding: 0, margin: 0, }, rightAction: { marginLeft: 8, }, clearBtn: { padding: 4, }, });