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;
}