diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index 2af80b029424..bf8eaa466d27 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -17,6 +17,7 @@ import useKeyboardShortcut from '@hooks/useKeyboardShortcut'; import useLocalize from '@hooks/useLocalize'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; +import * as InputUtils from '@libs/InputUtils'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import type {SearchOption} from '@libs/OptionsListUtils'; import {getAllTaxRates} from '@libs/PolicyUtils'; @@ -213,8 +214,22 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) } : undefined; + const shouldScrollRef = useRef(false); + const searchRouterInputRef = useRef(null); + // Trigger scrollToRight when input value changes and shouldScroll is true + useEffect(() => { + if (!searchRouterInputRef.current || !shouldScrollRef.current) { + return; + } + InputUtils.scrollToRight(searchRouterInputRef.current); + shouldScrollRef.current = false; + }, [debouncedInputValue]); + const onSearchQueryChange = useCallback( - (userQuery: string) => { + (userQuery: string, autoScrollToRight = false) => { + if (autoScrollToRight) { + shouldScrollRef.current = true; + } const updatedUserQuery = SearchAutocompleteUtils.getAutocompleteQueryWithComma(textInputValue, userQuery); setTextInputValue(updatedUserQuery); setAutocompleteQueryValue(updatedUserQuery); @@ -259,7 +274,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) if (item.searchItemType === CONST.SEARCH.SEARCH_ROUTER_ITEM_TYPE.CONTEXTUAL_SUGGESTION) { const searchQuery = getContextualSearchQuery(item); - onSearchQueryChange(`${searchQuery} `); + onSearchQueryChange(`${searchQuery} `, true); const autocompleteKey = getContextualSearchAutocompleteKey(item); if (autocompleteKey && item.autocompleteID) { @@ -330,6 +345,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) <> { diff --git a/src/components/Search/SearchRouter/SearchRouterInput.tsx b/src/components/Search/SearchRouter/SearchRouterInput.tsx index 3bd9146cac84..b88d0b4b2a10 100644 --- a/src/components/Search/SearchRouter/SearchRouterInput.tsx +++ b/src/components/Search/SearchRouter/SearchRouterInput.tsx @@ -1,10 +1,11 @@ -import type {ReactNode, RefObject} from 'react'; -import React, {useState} from 'react'; +import type {ForwardedRef, ReactNode, RefObject} from 'react'; +import React, {forwardRef, useState} from 'react'; import type {StyleProp, TextInputProps, ViewStyle} from 'react-native'; import {View} from 'react-native'; import FormHelpMessage from '@components/FormHelpMessage'; import type {SelectionListHandle} from '@components/SelectionList/types'; import TextInput from '@components/TextInput'; +import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -56,24 +57,27 @@ type SearchRouterInputProps = { isSearchingForReports?: boolean; } & Pick; -function SearchRouterInput({ - value, - onSearchQueryChange, - onSubmit = () => {}, - routerListRef, - isFullWidth, - disabled = false, - shouldShowOfflineMessage = false, - autoFocus = true, - onFocus, - onBlur, - caretHidden = false, - wrapperStyle, - wrapperFocusedStyle, - outerWrapperStyle, - rightComponent, - isSearchingForReports, -}: SearchRouterInputProps) { +function SearchRouterInput( + { + value, + onSearchQueryChange, + onSubmit = () => {}, + routerListRef, + isFullWidth, + disabled = false, + shouldShowOfflineMessage = false, + autoFocus = true, + onFocus, + onBlur, + caretHidden = false, + wrapperStyle, + wrapperFocusedStyle, + outerWrapperStyle, + rightComponent, + isSearchingForReports, + }: SearchRouterInputProps, + ref: ForwardedRef, +) { const styles = useThemeStyles(); const {translate} = useLocalize(); const [isFocused, setIsFocused] = useState(false); @@ -87,6 +91,7 @@ function SearchRouterInput({ {}; +const scrollToBottom: ScrollInput = () => {}; +const scrollToRight: ScrollInput = () => {}; const moveSelectionToEnd: MoveSelectiontoEnd = () => {}; -export {scrollToBottom, moveSelectionToEnd}; +export {scrollToBottom, moveSelectionToEnd, scrollToRight}; diff --git a/src/libs/InputUtils/index.ts b/src/libs/InputUtils/index.ts index 19943bf3132a..e992be5ca233 100644 --- a/src/libs/InputUtils/index.ts +++ b/src/libs/InputUtils/index.ts @@ -1,6 +1,6 @@ -import type {MoveSelectiontoEnd, ScrollToBottom} from './types'; +import type {MoveSelectiontoEnd, ScrollInput} from './types'; -const scrollToBottom: ScrollToBottom = (input) => { +const scrollToBottom: ScrollInput = (input) => { if (!('scrollTop' in input)) { return; } @@ -8,6 +8,15 @@ const scrollToBottom: ScrollToBottom = (input) => { input.scrollTop = input.scrollHeight; }; +const scrollToRight: ScrollInput = (input) => { + if (!('scrollLeft' in input)) { + return; + } + // Scroll to the far right + // eslint-disable-next-line no-param-reassign + input.scrollLeft = input.scrollWidth; +}; + const moveSelectionToEnd: MoveSelectiontoEnd = (input) => { if (!('setSelectionRange' in input)) { return; @@ -16,4 +25,4 @@ const moveSelectionToEnd: MoveSelectiontoEnd = (input) => { input.setSelectionRange(length, length); }; -export {scrollToBottom, moveSelectionToEnd}; +export {scrollToBottom, moveSelectionToEnd, scrollToRight}; diff --git a/src/libs/InputUtils/types.ts b/src/libs/InputUtils/types.ts index 875ac6b602e4..394cdb8722ab 100644 --- a/src/libs/InputUtils/types.ts +++ b/src/libs/InputUtils/types.ts @@ -1,6 +1,6 @@ import type {TextInput} from 'react-native'; -type ScrollToBottom = (input: HTMLInputElement | TextInput) => void; +type ScrollInput = (input: HTMLInputElement | TextInput) => void; type MoveSelectiontoEnd = (input: HTMLInputElement | TextInput) => void; -export type {ScrollToBottom, MoveSelectiontoEnd}; +export type {ScrollInput, MoveSelectiontoEnd};