From c3430c4633ee29e0733d5ef2f9c905c2e85c96a6 Mon Sep 17 00:00:00 2001 From: "Mikal S." <7761729+revam@users.noreply.github.com> Date: Tue, 3 Sep 2024 20:45:40 +0200 Subject: [PATCH] fix: fix auto focus for inputs (#1040) just don't look at the internals and you'll be good. --- .../Collection/Tmdb/EpisodeSelect.tsx | 1 + src/components/Input/Input.tsx | 13 ++++------- src/hooks/useAutoFocusRef.ts | 23 +++++++++++++++++++ 3 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 src/hooks/useAutoFocusRef.ts diff --git a/src/components/Collection/Tmdb/EpisodeSelect.tsx b/src/components/Collection/Tmdb/EpisodeSelect.tsx index 636434e4d..8a8c09d3a 100644 --- a/src/components/Collection/Tmdb/EpisodeSelect.tsx +++ b/src/components/Collection/Tmdb/EpisodeSelect.tsx @@ -123,6 +123,7 @@ const EpisodeSelect = React.memo((props: Props) => { className="z-[110] w-[var(--button-width)] rounded-lg bg-panel-background focus:outline-none" > { const { - autoFocus, + autoFocus = false, center, className, disabled, @@ -64,15 +65,9 @@ const Input = React.memo((props: Props) => { } = props; const bodyVisible = useContext(BodyVisibleContext); - const inputRef = useRef(null); + const inputRef = useAutoFocusRef(autoFocus, bodyVisible); const [isShow, setIsShow] = React.useState(false); - useEffect(() => { - if (autoFocus && bodyVisible && inputRef.current) { - inputRef.current?.focus(); - } - }, [autoFocus, bodyVisible]); - useEffect(() => { if (isOverlay) return; setIsShow(_ => false); diff --git a/src/hooks/useAutoFocusRef.ts b/src/hooks/useAutoFocusRef.ts new file mode 100644 index 000000000..015db10c8 --- /dev/null +++ b/src/hooks/useAutoFocusRef.ts @@ -0,0 +1,23 @@ +import type React from 'react'; + +import useEventCallback from './useEventCallback'; + +function useAutoFocusRef(autoFocus: boolean, bodyVisible: boolean): React.MutableRefObject { + // eslint-disable-next-line no-undef + const ref: React.MutableRefObject & { timeout?: NodeJS.Timeout } = useEventCallback( + (element: HTMLInputElement | null) => { + ref.current = element; + if (autoFocus && bodyVisible && element) { + if (ref.timeout) clearTimeout(ref.timeout); + ref.timeout = setTimeout(() => { + if (ref.timeout) delete ref.timeout; + element.focus(); + }, 0); + } + }, + // eslint-disable-next-line no-undef + ) as unknown as React.MutableRefObject & { timeout?: NodeJS.Timeout }; + return ref; +} + +export default useAutoFocusRef;