import { useState, useRef } from "react"; import styles from './GestureValueEditor.module.css' /** * Props for the GestureValueEditor component. * - value: current gesture value (controlled by parent) * - setValue: callback to update the gesture value in parent state * - placeholder: optional placeholder text for the input field */ type GestureValueEditorProps = { value: string; setValue: (value: string) => void; setType: (value: boolean) => void; placeholder?: string; }; /** * List of high-level gesture "tags". * These are human-readable categories or semantic labels. * In a real app, these would likely be loaded from an external source. */ const GESTURE_TAGS = ["above", "affirmative", "afford", "agitated", "all", "allright", "alright", "any", "assuage", "attemper", "back", "bashful", "beg", "beseech", "blank", "body language", "bored", "bow", "but", "call", "calm", "choose", "choice", "cloud", "cogitate", "cool", "crazy", "disappointed", "down", "earth", "empty", "embarrassed", "enthusiastic", "entire", "estimate", "except", "exalted", "excited", "explain", "far", "field", "floor", "forlorn", "friendly", "front", "frustrated", "gentle", "gift", "give", "ground", "happy", "hello", "her", "here", "hey", "hi", "him", "hopeless", "hysterical", "I", "implore", "indicate", "joyful", "me", "meditate", "modest", "negative", "nervous", "no", "not know", "nothing", "offer", "ok", "once upon a time", "oppose", "or", "pacify", "pick", "placate", "please", "present", "proffer", "quiet", "reason", "refute", "reject", "rousing", "sad", "select", "shamefaced", "show", "show sky", "sky", "soothe", "sun", "supplicate", "tablet", "tall", "them", "there", "think", "timid", "top", "unless", "up", "upstairs", "void", "warm", "winner", "yeah", "yes", "yoo-hoo", "you", "your", "zero", "zestful"]; /** * List of concrete gesture animation paths. * These represent specific animation assets and are used in "single" mode * with autocomplete-style selection, also would be loaded from an external source. */ const GESTURE_SINGLES = [ "animations/Stand/BodyTalk/Listening/Listening_1", "animations/Stand/BodyTalk/Listening/Listening_2", "animations/Stand/BodyTalk/Listening/Listening_3", "animations/Stand/BodyTalk/Listening/Listening_4", "animations/Stand/BodyTalk/Listening/Listening_5", "animations/Stand/BodyTalk/Listening/Listening_6", "animations/Stand/BodyTalk/Listening/Listening_7", "animations/Stand/BodyTalk/Speaking/BodyTalk_1", "animations/Stand/BodyTalk/Speaking/BodyTalk_10", "animations/Stand/BodyTalk/Speaking/BodyTalk_11", "animations/Stand/BodyTalk/Speaking/BodyTalk_12", "animations/Stand/BodyTalk/Speaking/BodyTalk_13", "animations/Stand/BodyTalk/Speaking/BodyTalk_14", "animations/Stand/BodyTalk/Speaking/BodyTalk_15", "animations/Stand/BodyTalk/Speaking/BodyTalk_16", "animations/Stand/BodyTalk/Speaking/BodyTalk_2", "animations/Stand/BodyTalk/Speaking/BodyTalk_3", "animations/Stand/BodyTalk/Speaking/BodyTalk_4", "animations/Stand/BodyTalk/Speaking/BodyTalk_5", "animations/Stand/BodyTalk/Speaking/BodyTalk_6", "animations/Stand/BodyTalk/Speaking/BodyTalk_7", "animations/Stand/BodyTalk/Speaking/BodyTalk_8", "animations/Stand/BodyTalk/Speaking/BodyTalk_9", "animations/Stand/BodyTalk/Thinking/Remember_1", "animations/Stand/BodyTalk/Thinking/Remember_2", "animations/Stand/BodyTalk/Thinking/Remember_3", "animations/Stand/BodyTalk/Thinking/ThinkingLoop_1", "animations/Stand/BodyTalk/Thinking/ThinkingLoop_2", "animations/Stand/Emotions/Negative/Angry_1", "animations/Stand/Emotions/Negative/Angry_2", "animations/Stand/Emotions/Negative/Angry_3", "animations/Stand/Emotions/Negative/Angry_4", "animations/Stand/Emotions/Negative/Anxious_1", "animations/Stand/Emotions/Negative/Bored_1", "animations/Stand/Emotions/Negative/Bored_2", "animations/Stand/Emotions/Negative/Disappointed_1", "animations/Stand/Emotions/Negative/Exhausted_1", "animations/Stand/Emotions/Negative/Exhausted_2", "animations/Stand/Emotions/Negative/Fear_1", "animations/Stand/Emotions/Negative/Fear_2", "animations/Stand/Emotions/Negative/Fearful_1", "animations/Stand/Emotions/Negative/Frustrated_1", "animations/Stand/Emotions/Negative/Humiliated_1", "animations/Stand/Emotions/Negative/Hurt_1", "animations/Stand/Emotions/Negative/Hurt_2", "animations/Stand/Emotions/Negative/Late_1", "animations/Stand/Emotions/Negative/Sad_1", "animations/Stand/Emotions/Negative/Sad_2", "animations/Stand/Emotions/Negative/Shocked_1", "animations/Stand/Emotions/Negative/Sorry_1", "animations/Stand/Emotions/Negative/Surprise_1", "animations/Stand/Emotions/Negative/Surprise_2", "animations/Stand/Emotions/Negative/Surprise_3", "animations/Stand/Emotions/Neutral/Alienated_1", "animations/Stand/Emotions/Neutral/AskForAttention_1", "animations/Stand/Emotions/Neutral/AskForAttention_2", "animations/Stand/Emotions/Neutral/AskForAttention_3", "animations/Stand/Emotions/Neutral/Cautious_1", "animations/Stand/Emotions/Neutral/Confused_1", "animations/Stand/Emotions/Neutral/Determined_1", "animations/Stand/Emotions/Neutral/Embarrassed_1", "animations/Stand/Emotions/Neutral/Hesitation_1", "animations/Stand/Emotions/Neutral/Innocent_1", "animations/Stand/Emotions/Neutral/Lonely_1", "animations/Stand/Emotions/Neutral/Mischievous_1", "animations/Stand/Emotions/Neutral/Puzzled_1", "animations/Stand/Emotions/Neutral/Sneeze", "animations/Stand/Emotions/Neutral/Stubborn_1", "animations/Stand/Emotions/Neutral/Suspicious_1", "animations/Stand/Emotions/Positive/Amused_1", "animations/Stand/Emotions/Positive/Confident_1", "animations/Stand/Emotions/Positive/Ecstatic_1", "animations/Stand/Emotions/Positive/Enthusiastic_1", "animations/Stand/Emotions/Positive/Excited_1", "animations/Stand/Emotions/Positive/Excited_2", "animations/Stand/Emotions/Positive/Excited_3", "animations/Stand/Emotions/Positive/Happy_1", "animations/Stand/Emotions/Positive/Happy_2", "animations/Stand/Emotions/Positive/Happy_3", "animations/Stand/Emotions/Positive/Happy_4", "animations/Stand/Emotions/Positive/Hungry_1", "animations/Stand/Emotions/Positive/Hysterical_1", "animations/Stand/Emotions/Positive/Interested_1", "animations/Stand/Emotions/Positive/Interested_2", "animations/Stand/Emotions/Positive/Laugh_1", "animations/Stand/Emotions/Positive/Laugh_2", "animations/Stand/Emotions/Positive/Laugh_3", "animations/Stand/Emotions/Positive/Mocker_1", "animations/Stand/Emotions/Positive/Optimistic_1", "animations/Stand/Emotions/Positive/Peaceful_1", "animations/Stand/Emotions/Positive/Proud_1", "animations/Stand/Emotions/Positive/Proud_2", "animations/Stand/Emotions/Positive/Proud_3", "animations/Stand/Emotions/Positive/Relieved_1", "animations/Stand/Emotions/Positive/Shy_1", "animations/Stand/Emotions/Positive/Shy_2", "animations/Stand/Emotions/Positive/Sure_1", "animations/Stand/Emotions/Positive/Winner_1", "animations/Stand/Emotions/Positive/Winner_2", "animations/Stand/Gestures/Angry_1", "animations/Stand/Gestures/Angry_2", "animations/Stand/Gestures/Angry_3", "animations/Stand/Gestures/BowShort_1", "animations/Stand/Gestures/BowShort_2", "animations/Stand/Gestures/BowShort_3", "animations/Stand/Gestures/But_1", "animations/Stand/Gestures/CalmDown_1", "animations/Stand/Gestures/CalmDown_2", "animations/Stand/Gestures/CalmDown_3", "animations/Stand/Gestures/CalmDown_4", "animations/Stand/Gestures/CalmDown_5", "animations/Stand/Gestures/CalmDown_6", "animations/Stand/Gestures/Choice_1", "animations/Stand/Gestures/ComeOn_1", "animations/Stand/Gestures/Confused_1", "animations/Stand/Gestures/Confused_2", "animations/Stand/Gestures/CountFive_1", "animations/Stand/Gestures/CountFour_1", "animations/Stand/Gestures/CountMore_1", "animations/Stand/Gestures/CountOne_1", "animations/Stand/Gestures/CountThree_1", "animations/Stand/Gestures/CountTwo_1", "animations/Stand/Gestures/Desperate_1", "animations/Stand/Gestures/Desperate_2", "animations/Stand/Gestures/Desperate_3", "animations/Stand/Gestures/Desperate_4", "animations/Stand/Gestures/Desperate_5", "animations/Stand/Gestures/DontUnderstand_1", "animations/Stand/Gestures/Enthusiastic_3", "animations/Stand/Gestures/Enthusiastic_4", "animations/Stand/Gestures/Enthusiastic_5", "animations/Stand/Gestures/Everything_1", "animations/Stand/Gestures/Everything_2", "animations/Stand/Gestures/Everything_3", "animations/Stand/Gestures/Everything_4", "animations/Stand/Gestures/Everything_6", "animations/Stand/Gestures/Excited_1", "animations/Stand/Gestures/Explain_1", "animations/Stand/Gestures/Explain_10", "animations/Stand/Gestures/Explain_11", "animations/Stand/Gestures/Explain_2", "animations/Stand/Gestures/Explain_3", "animations/Stand/Gestures/Explain_4", "animations/Stand/Gestures/Explain_5", "animations/Stand/Gestures/Explain_6", "animations/Stand/Gestures/Explain_7", "animations/Stand/Gestures/Explain_8", "animations/Stand/Gestures/Far_1", "animations/Stand/Gestures/Far_2", "animations/Stand/Gestures/Far_3", "animations/Stand/Gestures/Follow_1", "animations/Stand/Gestures/Give_1", "animations/Stand/Gestures/Give_2", "animations/Stand/Gestures/Give_3", "animations/Stand/Gestures/Give_4", "animations/Stand/Gestures/Give_5", "animations/Stand/Gestures/Give_6", "animations/Stand/Gestures/Great_1", "animations/Stand/Gestures/HeSays_1", "animations/Stand/Gestures/HeSays_2", "animations/Stand/Gestures/HeSays_3", "animations/Stand/Gestures/Hey_1", "animations/Stand/Gestures/Hey_10", "animations/Stand/Gestures/Hey_2", "animations/Stand/Gestures/Hey_3", "animations/Stand/Gestures/Hey_4", "animations/Stand/Gestures/Hey_6", "animations/Stand/Gestures/Hey_7", "animations/Stand/Gestures/Hey_8", "animations/Stand/Gestures/Hey_9", "animations/Stand/Gestures/Hide_1", "animations/Stand/Gestures/Hot_1", "animations/Stand/Gestures/Hot_2", "animations/Stand/Gestures/IDontKnow_1", "animations/Stand/Gestures/IDontKnow_2", "animations/Stand/Gestures/IDontKnow_3", "animations/Stand/Gestures/IDontKnow_4", "animations/Stand/Gestures/IDontKnow_5", "animations/Stand/Gestures/IDontKnow_6", "animations/Stand/Gestures/Joy_1", "animations/Stand/Gestures/Kisses_1", "animations/Stand/Gestures/Look_1", "animations/Stand/Gestures/Look_2", "animations/Stand/Gestures/Maybe_1", "animations/Stand/Gestures/Me_1", "animations/Stand/Gestures/Me_2", "animations/Stand/Gestures/Me_4", "animations/Stand/Gestures/Me_7", "animations/Stand/Gestures/Me_8", "animations/Stand/Gestures/Mime_1", "animations/Stand/Gestures/Mime_2", "animations/Stand/Gestures/Next_1", "animations/Stand/Gestures/No_1", "animations/Stand/Gestures/No_2", "animations/Stand/Gestures/No_3", "animations/Stand/Gestures/No_4", "animations/Stand/Gestures/No_5", "animations/Stand/Gestures/No_6", "animations/Stand/Gestures/No_7", "animations/Stand/Gestures/No_8", "animations/Stand/Gestures/No_9", "animations/Stand/Gestures/Nothing_1", "animations/Stand/Gestures/Nothing_2", "animations/Stand/Gestures/OnTheEvening_1", "animations/Stand/Gestures/OnTheEvening_2", "animations/Stand/Gestures/OnTheEvening_3", "animations/Stand/Gestures/OnTheEvening_4", "animations/Stand/Gestures/OnTheEvening_5", "animations/Stand/Gestures/Please_1", "animations/Stand/Gestures/Please_2", "animations/Stand/Gestures/Please_3", "animations/Stand/Gestures/Reject_1", "animations/Stand/Gestures/Reject_2", "animations/Stand/Gestures/Reject_3", "animations/Stand/Gestures/Reject_4", "animations/Stand/Gestures/Reject_5", "animations/Stand/Gestures/Reject_6", "animations/Stand/Gestures/Salute_1", "animations/Stand/Gestures/Salute_2", "animations/Stand/Gestures/Salute_3", "animations/Stand/Gestures/ShowFloor_1", "animations/Stand/Gestures/ShowFloor_2", "animations/Stand/Gestures/ShowFloor_3", "animations/Stand/Gestures/ShowFloor_4", "animations/Stand/Gestures/ShowFloor_5", "animations/Stand/Gestures/ShowSky_1", "animations/Stand/Gestures/ShowSky_10", "animations/Stand/Gestures/ShowSky_11", "animations/Stand/Gestures/ShowSky_12", "animations/Stand/Gestures/ShowSky_2", "animations/Stand/Gestures/ShowSky_3", "animations/Stand/Gestures/ShowSky_4", "animations/Stand/Gestures/ShowSky_5", "animations/Stand/Gestures/ShowSky_6", "animations/Stand/Gestures/ShowSky_7", "animations/Stand/Gestures/ShowSky_8", "animations/Stand/Gestures/ShowSky_9", "animations/Stand/Gestures/ShowTablet_1", "animations/Stand/Gestures/ShowTablet_2", "animations/Stand/Gestures/ShowTablet_3", "animations/Stand/Gestures/Shy_1", "animations/Stand/Gestures/Stretch_1", "animations/Stand/Gestures/Stretch_2", "animations/Stand/Gestures/Surprised_1", "animations/Stand/Gestures/TakePlace_1", "animations/Stand/Gestures/TakePlace_2", "animations/Stand/Gestures/Take_1", "animations/Stand/Gestures/Thinking_1", "animations/Stand/Gestures/Thinking_2", "animations/Stand/Gestures/Thinking_3", "animations/Stand/Gestures/Thinking_4", "animations/Stand/Gestures/Thinking_5", "animations/Stand/Gestures/Thinking_6", "animations/Stand/Gestures/Thinking_7", "animations/Stand/Gestures/Thinking_8", "animations/Stand/Gestures/This_1", "animations/Stand/Gestures/This_10", "animations/Stand/Gestures/This_11", "animations/Stand/Gestures/This_12", "animations/Stand/Gestures/This_13", "animations/Stand/Gestures/This_14", "animations/Stand/Gestures/This_15", "animations/Stand/Gestures/This_2", "animations/Stand/Gestures/This_3", "animations/Stand/Gestures/This_4", "animations/Stand/Gestures/This_5", "animations/Stand/Gestures/This_6", "animations/Stand/Gestures/This_7", "animations/Stand/Gestures/This_8", "animations/Stand/Gestures/This_9", "animations/Stand/Gestures/WhatSThis_1", "animations/Stand/Gestures/WhatSThis_10", "animations/Stand/Gestures/WhatSThis_11", "animations/Stand/Gestures/WhatSThis_12", "animations/Stand/Gestures/WhatSThis_13", "animations/Stand/Gestures/WhatSThis_14", "animations/Stand/Gestures/WhatSThis_15", "animations/Stand/Gestures/WhatSThis_16", "animations/Stand/Gestures/WhatSThis_2", "animations/Stand/Gestures/WhatSThis_3", "animations/Stand/Gestures/WhatSThis_4", "animations/Stand/Gestures/WhatSThis_5", "animations/Stand/Gestures/WhatSThis_6", "animations/Stand/Gestures/WhatSThis_7", "animations/Stand/Gestures/WhatSThis_8", "animations/Stand/Gestures/WhatSThis_9", "animations/Stand/Gestures/Whisper_1", "animations/Stand/Gestures/Wings_1", "animations/Stand/Gestures/Wings_2", "animations/Stand/Gestures/Wings_3", "animations/Stand/Gestures/Wings_4", "animations/Stand/Gestures/Wings_5", "animations/Stand/Gestures/Yes_1", "animations/Stand/Gestures/Yes_2", "animations/Stand/Gestures/Yes_3", "animations/Stand/Gestures/YouKnowWhat_1", "animations/Stand/Gestures/YouKnowWhat_2", "animations/Stand/Gestures/YouKnowWhat_3", "animations/Stand/Gestures/YouKnowWhat_4", "animations/Stand/Gestures/YouKnowWhat_5", "animations/Stand/Gestures/YouKnowWhat_6", "animations/Stand/Gestures/You_1", "animations/Stand/Gestures/You_2", "animations/Stand/Gestures/You_3", "animations/Stand/Gestures/You_4", "animations/Stand/Gestures/You_5", "animations/Stand/Gestures/Yum_1", "animations/Stand/Reactions/EthernetOff_1", "animations/Stand/Reactions/EthernetOn_1", "animations/Stand/Reactions/Heat_1", "animations/Stand/Reactions/Heat_2", "animations/Stand/Reactions/LightShine_1", "animations/Stand/Reactions/LightShine_2", "animations/Stand/Reactions/LightShine_3", "animations/Stand/Reactions/LightShine_4", "animations/Stand/Reactions/SeeColor_1", "animations/Stand/Reactions/SeeColor_2", "animations/Stand/Reactions/SeeColor_3", "animations/Stand/Reactions/SeeSomething_1", "animations/Stand/Reactions/SeeSomething_3", "animations/Stand/Reactions/SeeSomething_4", "animations/Stand/Reactions/SeeSomething_5", "animations/Stand/Reactions/SeeSomething_6", "animations/Stand/Reactions/SeeSomething_7", "animations/Stand/Reactions/SeeSomething_8", "animations/Stand/Reactions/ShakeBody_1", "animations/Stand/Reactions/ShakeBody_2", "animations/Stand/Reactions/ShakeBody_3", "animations/Stand/Reactions/TouchHead_1", "animations/Stand/Reactions/TouchHead_2", "animations/Stand/Reactions/TouchHead_3", "animations/Stand/Reactions/TouchHead_4", "animations/Stand/Waiting/AirGuitar_1", "animations/Stand/Waiting/BackRubs_1", "animations/Stand/Waiting/Bandmaster_1", "animations/Stand/Waiting/Binoculars_1", "animations/Stand/Waiting/BreathLoop_1", "animations/Stand/Waiting/BreathLoop_2", "animations/Stand/Waiting/BreathLoop_3", "animations/Stand/Waiting/CallSomeone_1", "animations/Stand/Waiting/Drink_1", "animations/Stand/Waiting/DriveCar_1", "animations/Stand/Waiting/Fitness_1", "animations/Stand/Waiting/Fitness_2", "animations/Stand/Waiting/Fitness_3", "animations/Stand/Waiting/FunnyDancer_1", "animations/Stand/Waiting/HappyBirthday_1", "animations/Stand/Waiting/Helicopter_1", "animations/Stand/Waiting/HideEyes_1", "animations/Stand/Waiting/HideHands_1", "animations/Stand/Waiting/Innocent_1", "animations/Stand/Waiting/Knight_1", "animations/Stand/Waiting/KnockEye_1", "animations/Stand/Waiting/KungFu_1", "animations/Stand/Waiting/LookHand_1", "animations/Stand/Waiting/LookHand_2", "animations/Stand/Waiting/LoveYou_1", "animations/Stand/Waiting/Monster_1", "animations/Stand/Waiting/MysticalPower_1", "animations/Stand/Waiting/PlayHands_1", "animations/Stand/Waiting/PlayHands_2", "animations/Stand/Waiting/PlayHands_3", "animations/Stand/Waiting/Relaxation_1", "animations/Stand/Waiting/Relaxation_2", "animations/Stand/Waiting/Relaxation_3", "animations/Stand/Waiting/Relaxation_4", "animations/Stand/Waiting/Rest_1", "animations/Stand/Waiting/Robot_1", "animations/Stand/Waiting/ScratchBack_1", "animations/Stand/Waiting/ScratchBottom_1", "animations/Stand/Waiting/ScratchEye_1", "animations/Stand/Waiting/ScratchHand_1", "animations/Stand/Waiting/ScratchHead_1", "animations/Stand/Waiting/ScratchLeg_1", "animations/Stand/Waiting/ScratchTorso_1", "animations/Stand/Waiting/ShowMuscles_1", "animations/Stand/Waiting/ShowMuscles_2", "animations/Stand/Waiting/ShowMuscles_3", "animations/Stand/Waiting/ShowMuscles_4", "animations/Stand/Waiting/ShowMuscles_5", "animations/Stand/Waiting/ShowSky_1", "animations/Stand/Waiting/ShowSky_2", "animations/Stand/Waiting/SpaceShuttle_1", "animations/Stand/Waiting/Stretch_1", "animations/Stand/Waiting/Stretch_2", "animations/Stand/Waiting/TakePicture_1", "animations/Stand/Waiting/Taxi_1", "animations/Stand/Waiting/Think_1", "animations/Stand/Waiting/Think_2", "animations/Stand/Waiting/Think_3", "animations/Stand/Waiting/Think_4", "animations/Stand/Waiting/Waddle_1", "animations/Stand/Waiting/Waddle_2", "animations/Stand/Waiting/WakeUp_1", "animations/Stand/Waiting/Zombie_1"] /** * Returns a gesture value editor component. * @returns JSX.Element */ export default function GestureValueEditor({ value, setValue, setType, placeholder = "Gesture name", }: GestureValueEditorProps) { /** Input mode: semantic tag vs concrete animation path */ const [mode, setMode] = useState<"single" | "tag">("tag"); /** Raw text value for single-gesture input */ const [customValue, setCustomValue] = useState(""); /** Autocomplete dropdown state */ const [showSuggestions, setShowSuggestions] = useState(true); const [filteredSuggestions, setFilteredSuggestions] = useState([]); /** Reserved for future click-outside / positioning logic */ const containerRef = useRef(null); /** Switch between tag and single input modes */ const handleModeChange = (newMode: "single" | "tag") => { setMode(newMode); if (newMode === "single") { setValue(customValue || value); setType(false); setFilteredSuggestions(GESTURE_SINGLES); setShowSuggestions(true); } else { // Clear value if it does not match a valid tag setType(true); const isValidTag = GESTURE_TAGS.some( tag => tag.toLowerCase() === value.toLowerCase() ); if (!isValidTag) setValue(""); setShowSuggestions(false); } }; /** Select a semantic gesture tag */ const handleTagSelect = (tag: string) => { setValue(tag); }; /** Update single-gesture input and filter suggestions */ const handleCustomChange = (newValue: string) => { setCustomValue(newValue); setValue(newValue); if (newValue.trim() === "") { setFilteredSuggestions(GESTURE_SINGLES); setShowSuggestions(true); } else { const filtered = GESTURE_SINGLES.filter(single => single.toLowerCase().includes(newValue.toLowerCase()) ); setFilteredSuggestions(filtered); setShowSuggestions(filtered.length > 0); } }; /** Commit autocomplete selection */ const handleSuggestionSelect = (suggestion: string) => { setCustomValue(suggestion); setValue(suggestion); setShowSuggestions(false); }; /** Refresh suggestions on refocus */ const handleInputFocus = () => { if (!customValue.trim()) return; const filtered = GESTURE_SINGLES.filter(single => single.toLowerCase().includes(customValue.toLowerCase()) ); setFilteredSuggestions(filtered); setShowSuggestions(filtered.length > 0); }; /** Exists to allow delayed blur handling if needed */ const handleInputBlur = (_e: React.FocusEvent) => {}; /** Build the JSX component */ return (
{/* Mode toggle */}
{mode === "single" ? (
{showSuggestions && (
{filteredSuggestions.map((suggestion) => (
handleSuggestionSelect(suggestion)} onMouseDown={(e) => e.preventDefault()} // prevent blur before click > {suggestion}
))}
)} handleCustomChange(e.target.value)} onFocus={handleInputFocus} onBlur={handleInputBlur} placeholder={placeholder} className={`${styles.textInput} ${showSuggestions ? styles.textInputWithSuggestions : ''}`} autoComplete="off" />
) : (
{GESTURE_TAGS.map((tag) => ( ))}
)}
); }