import React, {useState, useEffect} from 'react'; import { StyleSheet, TextInput, TouchableOpacity, Text, View, TextInputProps, Keyboard, NativeSyntheticEvent, TextInputSubmitEditingEventData, } from 'react-native'; import Animated, {interpolate} from 'react-native-reanimated'; import Icon from 'react-native-vector-icons/Feather'; import {normalize} from 'react-native-elements'; import {SCREEN_HEIGHT} from '../../utils'; const AnimatedIcon = Animated.createAnimatedComponent(Icon); interface SearchBarProps extends TextInputProps { onCancel: () => void; top: Animated.Value; searching: boolean; } const SearchBar: React.FC = ({ onFocus, onBlur, onChangeText, value, onCancel, searching, top, }) => { const handleSubmit = ( e: NativeSyntheticEvent, ) => { e.preventDefault(); Keyboard.dismiss(); }; // the search bar's default placeholder const DEFAULT_PLACEHOLDER: string = 'Search'; // the list of suggestions to cycle through. TODO: get this from the backend const PLACEHOLDERS: string[] = [ "Brown '21", "Brown '22", "Brown '23", "Brown '24", 'Trending on Tagg', 'New to Tagg', ]; /* * index & id of current placeholder, used in selecting next placeholder. -1 * indicates no suggestion, i.e. DEFAULT_PLACEHOLDER. TODO: make it seem more * random by tracking last 3-5 ids */ const [placeholderId, setPlaceholderId] = useState(-1); /* * the current placeholder, i.e. DEFAULT_PLACEHOLDER.concat(` ${PLACEHOLDERS[placeholderId]}`) */ const [placeholder, setPlaceholder] = useState(DEFAULT_PLACEHOLDER); /* * Utility function that generates a random integer in [0, xCeil). * * @param xCeil - the exclusive ceiling (getRandomInt(2) => 0 or 1, not 2) * @returns a random integer in the range [0, xCeil) */ const getRandomInt = (xCeil: number): number => { return Math.floor(Math.random() * Math.floor(xCeil)); }; /* * Handler for `placeholderChangeInterval` that sets the next placeholderId. */ const updatePlaceholder = () => { let nextPlaceholderId = getRandomInt(PLACEHOLDERS.length); while (nextPlaceholderId === placeholderId) { nextPlaceholderId = getRandomInt(PLACEHOLDERS.length); } setPlaceholderId(nextPlaceholderId); }; /* * Update `placeholder` when `placeholderId` is updated by the interval handler. */ useEffect(() => { if (placeholderId === -1) { setPlaceholder(DEFAULT_PLACEHOLDER); return; } setPlaceholder( DEFAULT_PLACEHOLDER.concat(` '${PLACEHOLDERS[placeholderId]}'`), ); }, [placeholderId]); /* * Sets the interval when the user begins searching and clears it when the user is done. */ useEffect(() => { if (!searching) return; updatePlaceholder(); const placeholderChangeInterval = setInterval(() => { updatePlaceholder(); }, 4500); return () => { clearInterval(placeholderChangeInterval); setPlaceholderId(-1); }; }, [searching]); /* * Animated nodes used in search bar activation animation. */ const marginRight: Animated.Node = interpolate(top, { inputRange: [-SCREEN_HEIGHT, 0], outputRange: [0, 58], }); const opacity: Animated.Node = interpolate(top, { inputRange: [-SCREEN_HEIGHT, 0], outputRange: [0, 1], }); return ( Cancel ); }; const styles = StyleSheet.create({ container: { height: 40, paddingHorizontal: 20, flexDirection: 'row', }, inputContainer: { flexGrow: 1, flexDirection: 'row', alignItems: 'center', paddingHorizontal: 8, borderRadius: 20, backgroundColor: '#F0F0F0', }, searchIcon: { marginRight: 8, }, input: { flex: 1, fontSize: 16, color: '#000', letterSpacing: normalize(0.5), }, cancelButton: { height: '100%', position: 'absolute', justifyContent: 'center', paddingHorizontal: 8, }, cancelText: { color: '#818181', fontWeight: '500', }, }); export default SearchBar;