From 6c81cecc4354996a711ec71d1ac67ae2276b61cc Mon Sep 17 00:00:00 2001 From: printfn Date: Fri, 6 Dec 2024 08:25:26 +0000 Subject: [PATCH] Extract components --- web/src/App.tsx | 30 +++++----------------------- web/src/components/NewTabLink.tsx | 14 +++++++++++++ web/src/components/PendingOutput.tsx | 30 ++++++++++++++++++++++++++++ web/src/index.css | 2 +- 4 files changed, 50 insertions(+), 26 deletions(-) create mode 100644 web/src/components/NewTabLink.tsx create mode 100644 web/src/components/PendingOutput.tsx diff --git a/web/src/App.tsx b/web/src/App.tsx index e4dcb266..853add59 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,7 +1,8 @@ import { type KeyboardEvent, type ReactNode, useCallback, useEffect, useRef, useState, useTransition } from 'react'; -import { ThreeDotsScale } from 'react-svg-spinners'; import { fend } from './lib/fend'; import { useCurrentInput } from './hooks/useCurrentInput'; +import NewTabLink from './components/NewTabLink'; +import PendingOutput from './components/PendingOutput'; const examples = ` > 5'10" to cm @@ -33,31 +34,12 @@ const exampleContent = (

); -function NewTabLink({ children, href }: { children: ReactNode; href: string }) { - return ( - - {children} - - ); -} - export default function App({ widget = false }: { widget?: boolean }) { const [output, setOutput] = useState(widget ? <> : exampleContent); const { currentInput, submit, onInput, upArrow, downArrow } = useCurrentInput(); const [variables, setVariables] = useState(''); - const [hint, setHint] = useState(''); - useEffect(() => { - void (async () => { - const result = await fend(currentInput, 100, variables); - if (!result.ok) { - setHint(''); - } else { - setHint(result.result); - } - })(); - }, [currentInput, variables]); const inputText = useRef(null); - const inputHint = useRef(null); + const pendingOutput = useRef(null); const focus = useCallback(() => { // allow the user to select text for copying and // pasting, but if text is deselected (collapsed) @@ -121,7 +103,7 @@ export default function App({ widget = false }: { widget?: boolean }) { {result} )); - inputHint.current?.scrollIntoView(); + pendingOutput.current?.scrollIntoView(); }); }, [currentInput, submit, variables, onInput, downArrow, upArrow], @@ -157,9 +139,7 @@ export default function App({ widget = false }: { widget?: boolean }) { autoFocus /> -

- {hint || (isPending ? : <> )} -

+ ); diff --git a/web/src/components/NewTabLink.tsx b/web/src/components/NewTabLink.tsx new file mode 100644 index 00000000..1bddfe5e --- /dev/null +++ b/web/src/components/NewTabLink.tsx @@ -0,0 +1,14 @@ +import type { ReactNode } from 'react'; + +type Props = { + children: ReactNode; + href: string; +}; + +export default function NewTabLink({ children, href }: Props) { + return ( + + {children} + + ); +} diff --git a/web/src/components/PendingOutput.tsx b/web/src/components/PendingOutput.tsx new file mode 100644 index 00000000..22b6a0f9 --- /dev/null +++ b/web/src/components/PendingOutput.tsx @@ -0,0 +1,30 @@ +import { useEffect, useState, type Ref } from 'react'; +import { ThreeDotsScale } from 'react-svg-spinners'; +import { fend } from '../lib/fend'; + +type Props = { + ref: Ref; + currentInput: string; + variables: string; + isPending: boolean; +}; + +export default function PendingOutput({ ref, currentInput, variables, isPending }: Props) { + const [hint, setHint] = useState(''); + useEffect(() => { + void (async () => { + const result = await fend(currentInput, 100, variables); + if (!result.ok) { + setHint(''); + } else { + setHint(result.result); + } + })(); + }, [currentInput, variables]); + + return ( +

+ {hint || (isPending ? : <> )} +

+ ); +} diff --git a/web/src/index.css b/web/src/index.css index c3c1cb9d..bf6b5db8 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -50,7 +50,7 @@ main { } #output p, -#input-hint { +#pending-output { white-space: pre-wrap; word-break: break-all; }