aboutsummaryrefslogtreecommitdiff
path: root/src/console/components/CommandPrompt.tsx
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2021-04-12 13:09:09 +0000
committerGitHub <noreply@github.com>2021-04-12 13:09:09 +0000
commitd80d0f87b82ba4bd74ed9b2bb7354421a28a11b3 (patch)
tree691185ad88418d0f44c236d0913cf5c425b29b23 /src/console/components/CommandPrompt.tsx
parentea73c900f66107fd4a5b2f3b05080bcf643c94ea (diff)
parent8a5bba1da639355a25da8c279a9f1cf0a7300a9f (diff)
Merge pull request #1098 from ueokande/replace-redux-with-react-hooks
Refactor state management with React Hooks on Console
Diffstat (limited to 'src/console/components/CommandPrompt.tsx')
-rw-r--r--src/console/components/CommandPrompt.tsx116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/console/components/CommandPrompt.tsx b/src/console/components/CommandPrompt.tsx
new file mode 100644
index 0000000..1b6281b
--- /dev/null
+++ b/src/console/components/CommandPrompt.tsx
@@ -0,0 +1,116 @@
+import React from "react";
+import Completion from "./console/Completion";
+import Input from "./console//Input";
+import styled from "styled-components";
+import { useCompletions, useSelectCompletion } from "../completion/hooks";
+import useAutoResize from "../hooks/useAutoResize";
+import { CompletionProvider } from "../completion/provider";
+import { useExecCommand, useHide } from "../app/hooks";
+
+const COMPLETION_MAX_ITEMS = 33;
+
+const ConsoleWrapper = styled.div`
+ border-top: 1px solid gray;
+`;
+
+interface Props {
+ initialInputValue: string;
+}
+
+const CommandPromptInner: React.FC<Props> = ({ initialInputValue }) => {
+ const hide = useHide();
+ const [inputValue, setInputValue] = React.useState(initialInputValue);
+ const { completions, updateCompletions } = useCompletions();
+ const {
+ select,
+ currentValue,
+ selectNext,
+ selectPrev,
+ } = useSelectCompletion();
+ const execCommand = useExecCommand();
+
+ useAutoResize();
+
+ const onBlur = () => {
+ hide();
+ };
+
+ const isCancelKey = React.useCallback(
+ (e: React.KeyboardEvent<HTMLInputElement>) =>
+ e.key === "Escape" ||
+ (e.ctrlKey && e.key === "[") ||
+ (e.ctrlKey && e.key === "c"),
+ []
+ );
+
+ const isNextKey = React.useCallback(
+ (e: React.KeyboardEvent<HTMLInputElement>) =>
+ (!e.shiftKey && e.key === "Tab") || (e.ctrlKey && e.key === "n"),
+ []
+ );
+
+ const isPrevKey = React.useCallback(
+ (e: React.KeyboardEvent<HTMLInputElement>) =>
+ (e.shiftKey && e.key === "Tab") || (e.ctrlKey && e.key === "p"),
+ []
+ );
+
+ const isEnterKey = React.useCallback(
+ (e: React.KeyboardEvent<HTMLInputElement>) =>
+ e.key === "Enter" || (e.ctrlKey && e.key === "m"),
+ []
+ );
+
+ const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
+ if (isCancelKey(e)) {
+ hide();
+ } else if (isEnterKey(e)) {
+ const value = (e.target as HTMLInputElement).value;
+ execCommand(value);
+ hide();
+ } else if (isNextKey(e)) {
+ selectNext();
+ } else if (isPrevKey(e)) {
+ selectPrev();
+ } else {
+ return;
+ }
+
+ e.stopPropagation();
+ e.preventDefault();
+ };
+
+ const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+ const text = e.target.value;
+ setInputValue(text);
+ };
+
+ React.useEffect(() => {
+ updateCompletions(inputValue);
+ }, [inputValue]);
+
+ return (
+ <ConsoleWrapper>
+ <Completion
+ size={COMPLETION_MAX_ITEMS}
+ completions={completions}
+ select={select}
+ />
+ <Input
+ prompt={":"}
+ onBlur={onBlur}
+ onKeyDown={onKeyDown}
+ onChange={onChange}
+ value={select == -1 ? inputValue : currentValue}
+ />
+ </ConsoleWrapper>
+ );
+};
+
+const CommandPrompt: React.FC<Props> = ({ initialInputValue }) => (
+ <CompletionProvider initialInputValue={initialInputValue}>
+ <CommandPromptInner initialInputValue={initialInputValue} />
+ </CompletionProvider>
+);
+
+export default CommandPrompt;