Skip to content

Commit

Permalink
Extract components
Browse files Browse the repository at this point in the history
  • Loading branch information
printfn committed Dec 6, 2024
1 parent 3fb08f4 commit 6c81cec
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 26 deletions.
30 changes: 5 additions & 25 deletions web/src/App.tsx
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -33,31 +34,12 @@ const exampleContent = (
</p>
);

function NewTabLink({ children, href }: { children: ReactNode; href: string }) {
return (
<a rel="noreferrer noopener" target="_blank" href={`https://${href}`}>
{children}
</a>
);
}

export default function App({ widget = false }: { widget?: boolean }) {
const [output, setOutput] = useState<ReactNode>(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<HTMLTextAreaElement>(null);
const inputHint = useRef<HTMLParagraphElement>(null);
const pendingOutput = useRef<HTMLParagraphElement>(null);
const focus = useCallback(() => {
// allow the user to select text for copying and
// pasting, but if text is deselected (collapsed)
Expand Down Expand Up @@ -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],
Expand Down Expand Up @@ -157,9 +139,7 @@ export default function App({ widget = false }: { widget?: boolean }) {
autoFocus
/>
</div>
<p id="input-hint" ref={inputHint}>
{hint || (isPending ? <ThreeDotsScale /> : <>&nbsp;</>)}
</p>
<PendingOutput ref={pendingOutput} currentInput={currentInput} variables={variables} isPending={isPending} />
</div>
</main>
);
Expand Down
14 changes: 14 additions & 0 deletions web/src/components/NewTabLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { ReactNode } from 'react';

type Props = {
children: ReactNode;
href: string;
};

export default function NewTabLink({ children, href }: Props) {
return (
<a rel="noreferrer noopener" target="_blank" href={`https://${href}`}>
{children}
</a>
);
}
30 changes: 30 additions & 0 deletions web/src/components/PendingOutput.tsx
Original file line number Diff line number Diff line change
@@ -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<HTMLParagraphElement>;
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 (
<p id="pending-output" ref={ref}>
{hint || (isPending ? <ThreeDotsScale /> : <>&nbsp;</>)}
</p>
);
}
2 changes: 1 addition & 1 deletion web/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ main {
}

#output p,
#input-hint {
#pending-output {
white-space: pre-wrap;
word-break: break-all;
}
Expand Down

0 comments on commit 6c81cec

Please sign in to comment.