diff options
Diffstat (limited to 'src/console/components')
-rw-r--r-- | src/console/components/CommandPrompt.tsx | 116 | ||||
-rw-r--r-- | src/console/components/Console.tsx | 288 | ||||
-rw-r--r-- | src/console/components/ErrorMessage.tsx | 15 | ||||
-rw-r--r-- | src/console/components/FindPrompt.tsx | 58 | ||||
-rw-r--r-- | src/console/components/InfoMessage.tsx | 15 | ||||
-rw-r--r-- | src/console/components/Theme.ts | 53 | ||||
-rw-r--r-- | src/console/components/console/Completion.tsx | 136 | ||||
-rw-r--r-- | src/console/components/console/CompletionItem.tsx | 8 | ||||
-rw-r--r-- | src/console/components/console/CompletionTitle.tsx | 10 | ||||
-rw-r--r-- | src/console/components/console/Input.tsx | 61 | ||||
-rw-r--r-- | src/console/components/console/Message.tsx | 33 |
11 files changed, 334 insertions, 459 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; diff --git a/src/console/components/Console.tsx b/src/console/components/Console.tsx index 18a6632..db18fa0 100644 --- a/src/console/components/Console.tsx +++ b/src/console/components/Console.tsx @@ -1,251 +1,39 @@ -import { connect } from "react-redux"; import React from "react"; -import Input from "./console/Input"; -import Completion from "./console/Completion"; -import Message from "./console/Message"; -import * as consoleActions from "../../console/actions/console"; -import { State as AppState } from "../reducers"; -import CommandLineParser, { - InputPhase, -} from "../commandline/CommandLineParser"; -import { Command } from "../../shared/Command"; -import ColorScheme from "../../shared/ColorScheme"; -import { LightTheme, DarkTheme } from "./Theme"; -import styled from "./Theme"; -import { ThemeProvider } from "styled-components"; -import ConsoleFrameClient from "../clients/ConsoleFrameClient"; - -const ConsoleWrapper = styled.div` - border-top: 1px solid gray; -`; - -const COMPLETION_MAX_ITEMS = 33; - -type StateProps = ReturnType<typeof mapStateToProps>; -interface DispatchProps { - dispatch: (action: any) => void; -} -type Props = StateProps & DispatchProps; - -class Console extends React.Component<Props> { - private input: React.RefObject<Input>; - - private commandLineParser: CommandLineParser = new CommandLineParser(); - private consoleFrameClient = new ConsoleFrameClient(); - - constructor(props: Props) { - super(props); - - this.input = React.createRef(); - } - - onBlur() { - if (this.props.mode === "command" || this.props.mode === "find") { - return this.props.dispatch(consoleActions.hideCommand()); - } - } - - doEnter(e: React.KeyboardEvent<HTMLInputElement>) { - e.stopPropagation(); - e.preventDefault(); - - const value = (e.target as HTMLInputElement).value; - if (this.props.mode === "command") { - return this.props.dispatch(consoleActions.enterCommand(value)); - } else if (this.props.mode === "find") { - return this.props.dispatch( - consoleActions.enterFind(value === "" ? undefined : value) - ); - } - } - - selectNext(e: React.KeyboardEvent<HTMLInputElement>) { - this.props.dispatch(consoleActions.completionNext()); - e.stopPropagation(); - e.preventDefault(); - } - - selectPrev(e: React.KeyboardEvent<HTMLInputElement>) { - this.props.dispatch(consoleActions.completionPrev()); - e.stopPropagation(); - e.preventDefault(); - } - - onKeyDown(e: React.KeyboardEvent<HTMLInputElement>) { - switch (e.key) { - case "Escape": - return this.props.dispatch(consoleActions.hideCommand()); - case "Enter": - return this.doEnter(e); - case "Tab": - if (e.shiftKey) { - this.props.dispatch(consoleActions.completionPrev()); - } else { - this.props.dispatch(consoleActions.completionNext()); - } - e.stopPropagation(); - e.preventDefault(); - break; - case "[": - if (e.ctrlKey) { - e.preventDefault(); - return this.props.dispatch(consoleActions.hideCommand()); - } - break; - case "c": - if (e.ctrlKey) { - e.preventDefault(); - return this.props.dispatch(consoleActions.hideCommand()); - } - break; - case "m": - if (e.ctrlKey) { - return this.doEnter(e); - } - break; - case "n": - if (e.ctrlKey) { - this.selectNext(e); - } - break; - case "p": - if (e.ctrlKey) { - this.selectPrev(e); - } - break; - } - } - - onChange(e: React.ChangeEvent<HTMLInputElement>) { - const text = e.target.value; - this.props.dispatch(consoleActions.setConsoleText(text)); - if (this.props.mode !== "command") { - return; - } - this.updateCompletions(text); - } - - componentDidUpdate(prevProps: Props) { - if (prevProps.mode !== "command" && this.props.mode === "command") { - this.updateCompletions(this.props.consoleText); - this.focus(); - } else if (prevProps.mode !== "find" && this.props.mode === "find") { - this.focus(); - } - - const { - scrollWidth: width, - scrollHeight: height, - } = document.getElementById("vimvixen-console")!; - this.consoleFrameClient.resize(width, height); - } - - render() { - let theme = this.props.colorscheme; - if (this.props.colorscheme === ColorScheme.System) { - if ( - window.matchMedia && - window.matchMedia("(prefers-color-scheme: dark)").matches - ) { - theme = ColorScheme.Dark; - } else { - theme = ColorScheme.Light; - } - } - - switch (this.props.mode) { - case "command": - case "find": - return ( - <ThemeProvider - theme={theme === ColorScheme.Dark ? DarkTheme : LightTheme} - > - <ConsoleWrapper> - <Completion - size={COMPLETION_MAX_ITEMS} - completions={this.props.completions} - select={this.props.select} - /> - <Input - ref={this.input} - mode={this.props.mode} - onBlur={this.onBlur.bind(this)} - onKeyDown={this.onKeyDown.bind(this)} - onChange={this.onChange.bind(this)} - value={this.props.consoleText} - /> - </ConsoleWrapper> - </ThemeProvider> - ); - case "info": - case "error": - return ( - <ThemeProvider - theme={theme === ColorScheme.Dark ? DarkTheme : LightTheme} - > - <Message mode={this.props.mode}>{this.props.messageText}</Message> - </ThemeProvider> - ); - default: - return null; - } - } - - async focus() { - this.props.dispatch(consoleActions.setColorScheme()); - - window.focus(); - if (this.input.current) { - this.input.current.focus(); - } - } - - private updateCompletions(text: string) { - const phase = this.commandLineParser.inputPhase(text); - if (phase === InputPhase.OnCommand) { - return this.props.dispatch(consoleActions.getCommandCompletions(text)); - } else { - const cmd = this.commandLineParser.parse(text); - switch (cmd.command) { - case Command.Open: - case Command.TabOpen: - case Command.WindowOpen: - this.props.dispatch( - consoleActions.getOpenCompletions( - this.props.completionTypes, - text, - cmd.command, - cmd.args - ) - ); - break; - case Command.Buffer: - this.props.dispatch( - consoleActions.getTabCompletions(text, cmd.command, cmd.args, false) - ); - break; - case Command.BufferDelete: - case Command.BuffersDelete: - this.props.dispatch( - consoleActions.getTabCompletions(text, cmd.command, cmd.args, true) - ); - break; - case Command.BufferDeleteForce: - case Command.BuffersDeleteForce: - this.props.dispatch( - consoleActions.getTabCompletions(text, cmd.command, cmd.args, false) - ); - break; - case Command.Set: - this.props.dispatch( - consoleActions.getPropertyCompletions(text, cmd.command, cmd.args) - ); - break; - } - } - } -} - -const mapStateToProps = (state: AppState) => ({ ...state }); - -export default connect(mapStateToProps)(Console); +import FindPrompt from "./FindPrompt"; +import CommandPrompt from "./CommandPrompt"; +import InfoMessage from "./InfoMessage"; +import ErrorMessage from "./ErrorMessage"; +import { useColorSchemeRefresh } from "../colorscheme/hooks"; +import { + useCommandMode, + useErrorMessage, + useFindMode, + useInfoMessage, +} from "../app/hooks"; + +const Console: React.FC = () => { + const refreshColorScheme = useColorSchemeRefresh(); + const { visible: visibleCommand, initialInputValue } = useCommandMode(); + const { visible: visibleFind } = useFindMode(); + const { visible: visibleInfo, message: infoMessage } = useInfoMessage(); + const { visible: visibleError, message: errorMessage } = useErrorMessage(); + + React.useEffect(() => { + if (visibleCommand || visibleFind || visibleInfo || visibleError) { + refreshColorScheme(); + } + }, [visibleCommand, visibleFind, visibleInfo, visibleError]); + + if (visibleCommand) { + return <CommandPrompt initialInputValue={initialInputValue} />; + } else if (visibleFind) { + return <FindPrompt />; + } else if (visibleInfo) { + return <InfoMessage>{infoMessage}</InfoMessage>; + } else if (visibleError) { + return <ErrorMessage>{errorMessage}</ErrorMessage>; + } + return null; +}; + +export default Console; diff --git a/src/console/components/ErrorMessage.tsx b/src/console/components/ErrorMessage.tsx new file mode 100644 index 0000000..f8d5ae7 --- /dev/null +++ b/src/console/components/ErrorMessage.tsx @@ -0,0 +1,15 @@ +import React from "react"; +import styled from "../colorscheme/styled"; + +const Wrapper = styled.p` + border-top: 1px solid gray; + background-color: ${({ theme }) => theme.consoleErrorBackground}; + color: ${({ theme }) => theme.consoleErrorForeground}; + font-weight: bold; +`; + +const ErrorMessage: React.FC = ({ children }) => { + return <Wrapper role="alert">{children}</Wrapper>; +}; + +export default ErrorMessage; diff --git a/src/console/components/FindPrompt.tsx b/src/console/components/FindPrompt.tsx new file mode 100644 index 0000000..c437d16 --- /dev/null +++ b/src/console/components/FindPrompt.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import Input from "./console/Input"; +import styled from "styled-components"; +import useAutoResize from "../hooks/useAutoResize"; +import { useExecFind, useHide } from "../app/hooks"; + +const ConsoleWrapper = styled.div` + border-top: 1px solid gray; +`; + +const FindPrompt: React.FC = () => { + const [inputValue, setInputValue] = React.useState(""); + const hide = useHide(); + const execFind = useExecFind(); + + const onBlur = () => { + hide(); + }; + + useAutoResize(); + + const doEnter = (e: React.KeyboardEvent<HTMLInputElement>) => { + e.stopPropagation(); + e.preventDefault(); + + const value = (e.target as HTMLInputElement).value; + execFind(value === "" ? undefined : value); + }; + + const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { + switch (e.key) { + case "Escape": + hide(); + break; + case "Enter": + doEnter(e); + break; + } + }; + + const onChange = (e: React.ChangeEvent<HTMLInputElement>) => { + setInputValue(e.target.value); + }; + + return ( + <ConsoleWrapper> + <Input + prompt={"/"} + onBlur={onBlur} + onKeyDown={onKeyDown} + onChange={onChange} + value={inputValue} + /> + </ConsoleWrapper> + ); +}; + +export default FindPrompt; diff --git a/src/console/components/InfoMessage.tsx b/src/console/components/InfoMessage.tsx new file mode 100644 index 0000000..ccd9bcf --- /dev/null +++ b/src/console/components/InfoMessage.tsx @@ -0,0 +1,15 @@ +import React from "react"; +import styled from "../colorscheme/styled"; + +const Wrapper = styled.p` + border-top: 1px solid gray; + background-color: ${({ theme }) => theme.consoleInfoBackground}; + color: ${({ theme }) => theme.consoleInfoForeground}; + font-weight: normal; +`; + +const InfoMessage: React.FC = ({ children }) => { + return <Wrapper role="status">{children}</Wrapper>; +}; + +export default InfoMessage; diff --git a/src/console/components/Theme.ts b/src/console/components/Theme.ts deleted file mode 100644 index dd7baa5..0000000 --- a/src/console/components/Theme.ts +++ /dev/null @@ -1,53 +0,0 @@ -import baseStyled, { ThemedStyledInterface } from "styled-components"; - -type Theme = { - completionTitleBackground: string; - completionTitleForeground: string; - completionItemBackground: string; - completionItemForeground: string; - completionItemDescriptionForeground: string; - completionSelectedBackground: string; - completionSelectedForeground: string; - commandBackground: string; - commandForeground: string; - consoleErrorBackground: string; - consoleErrorForeground: string; - consoleInfoBackground: string; - consoleInfoForeground: string; -}; - -export const LightTheme: Theme = { - completionTitleBackground: "lightgray", - completionTitleForeground: "#000000", - completionItemBackground: "#ffffff", - completionItemForeground: "#000000", - completionItemDescriptionForeground: "#008000", - completionSelectedBackground: "#ffff00", - completionSelectedForeground: "#000000", - commandBackground: "#ffffff", - commandForeground: "#000000", - consoleErrorBackground: "#ff0000", - consoleErrorForeground: "#ffffff", - consoleInfoBackground: "#ffffff", - consoleInfoForeground: "#018786", -}; - -export const DarkTheme: Theme = { - completionTitleBackground: "#052027", - completionTitleForeground: "white", - completionItemBackground: "#2f474f", - completionItemForeground: "white", - completionItemDescriptionForeground: "#86fab0", - completionSelectedBackground: "#eeff41", - completionSelectedForeground: "#000000", - commandBackground: "#052027", - commandForeground: "white", - consoleErrorBackground: "red", - consoleErrorForeground: "white", - consoleInfoBackground: "#052027", - consoleInfoForeground: "#ffffff", -}; - -const styled = baseStyled as ThemedStyledInterface<Theme>; - -export default styled; diff --git a/src/console/components/console/Completion.tsx b/src/console/components/console/Completion.tsx index 09ae278..ed271aa 100644 --- a/src/console/components/console/Completion.tsx +++ b/src/console/components/console/Completion.tsx @@ -19,97 +19,85 @@ interface Props { completions: Group[]; } -interface State { - viewOffset: number; - select: number; -} - -class Completion extends React.Component<Props, State> { - constructor(props: Props) { - super(props); - this.state = { viewOffset: 0, select: -1 }; - } +const Completion: React.FC<Props> = ({ select, size, completions }) => { + const [viewOffset, setViewOffset] = React.useState(0); + const [prevSelect, setPrevSelect] = React.useState(-1); - static getDerivedStateFromProps(nextProps: Props, prevState: State) { - if (prevState.select === nextProps.select) { - return null; + React.useEffect(() => { + if (select === prevSelect) { + return; } const viewSelect = (() => { let index = 0; - for (let i = 0; i < nextProps.completions.length; ++i) { + for (let i = 0; i < completions.length; ++i) { ++index; - const g = nextProps.completions[i]; - if (nextProps.select + i + 1 < index + g.items.length) { - return nextProps.select + i + 1; + const g = completions[i]; + if (select + i + 1 < index + g.items.length) { + return select + i + 1; } index += g.items.length; } return -1; })(); - let viewOffset = 0; - if (nextProps.select < 0) { - viewOffset = 0; - } else if (prevState.select < nextProps.select) { - viewOffset = Math.max( - prevState.viewOffset, - viewSelect - nextProps.size + 1 - ); - } else if (prevState.select > nextProps.select) { - viewOffset = Math.min(prevState.viewOffset, viewSelect); - } - return { viewOffset, select: nextProps.select }; - } + const nextViewOffset = (() => { + if (prevSelect < select) { + return Math.max(viewOffset, viewSelect - size + 1); + } else if (prevSelect > select) { + return Math.min(viewOffset, viewSelect); + } + return 0; + })(); + + setPrevSelect(select); + setViewOffset(nextViewOffset); + }, [select]); - render() { - let itemIndex = 0; - let viewIndex = 0; - const groups: Array<JSX.Element> = []; - const viewOffset = this.state.viewOffset; - const viewSize = this.props.size; + let itemIndex = 0; + let viewIndex = 0; + const groups: Array<JSX.Element> = []; - this.props.completions.forEach((group, groupIndex) => { - const items = []; - const title = ( - <CompletionTitle - id={`title-${groupIndex}`} - key={`group-${groupIndex}`} - shown={viewOffset <= viewIndex && viewIndex < viewOffset + viewSize} - title={group.name} + completions.forEach((group, groupIndex) => { + const items = []; + const title = ( + <CompletionTitle + id={`title-${groupIndex}`} + key={`group-${groupIndex}`} + shown={viewOffset <= viewIndex && viewIndex < viewOffset + size} + title={group.name} + /> + ); + ++viewIndex; + for (const item of group.items) { + items.push( + <CompletionItem + shown={viewOffset <= viewIndex && viewIndex < viewOffset + size} + key={`item-${itemIndex}`} + icon={item.icon} + caption={item.caption} + url={item.url} + highlight={itemIndex === select} + aria-selected={itemIndex === select} + role="menuitem" /> ); ++viewIndex; - for (const item of group.items) { - items.push( - <CompletionItem - shown={viewOffset <= viewIndex && viewIndex < viewOffset + viewSize} - key={`item-${itemIndex}`} - icon={item.icon} - caption={item.caption} - url={item.url} - highlight={itemIndex === this.props.select} - aria-selected={itemIndex === this.props.select} - role="menuitem" - /> - ); - ++viewIndex; - ++itemIndex; - } - groups.push( - <div - key={`group-${groupIndex}`} - role="group" - aria-describedby={`title-${groupIndex}`} - > - {title} - <ul>{items}</ul> - </div> - ); - }); + ++itemIndex; + } + groups.push( + <div + key={`group-${groupIndex}`} + role="group" + aria-describedby={`title-${groupIndex}`} + > + {title} + <ul>{items}</ul> + </div> + ); + }); - return <div role="menu">{groups}</div>; - } -} + return <div role="menu">{groups}</div>; +}; export default Completion; diff --git a/src/console/components/console/CompletionItem.tsx b/src/console/components/console/CompletionItem.tsx index 5f2f9f6..2de1375 100644 --- a/src/console/components/console/CompletionItem.tsx +++ b/src/console/components/console/CompletionItem.tsx @@ -1,5 +1,5 @@ import React from "react"; -import styled from "../Theme"; +import styled from "../../colorscheme/styled"; const Container = styled.li<{ shown: boolean; @@ -38,7 +38,7 @@ const Description = styled.span` overflow: hidden; `; -interface Props { +interface Props extends React.HTMLAttributes<HTMLElement> { shown: boolean; highlight: boolean; caption?: string; @@ -46,9 +46,7 @@ interface Props { icon?: string; } -const CompletionItem: React.FC<React.HTMLAttributes<HTMLElement> & Props> = ( - props -) => ( +const CompletionItem: React.FC<Props> = (props) => ( <Container icon={props.icon || ""} aria-labelledby={`completion-item-${props.caption}`} diff --git a/src/console/components/console/CompletionTitle.tsx b/src/console/components/console/CompletionTitle.tsx index ec2fc8b..4018b3f 100644 --- a/src/console/components/console/CompletionTitle.tsx +++ b/src/console/components/console/CompletionTitle.tsx @@ -1,5 +1,5 @@ import React from "react"; -import styled from "../Theme"; +import styled from "../../colorscheme/styled"; const Li = styled.li<{ shown: boolean }>` display: ${({ shown }) => (shown ? "display" : "none")}; @@ -10,13 +10,13 @@ const Li = styled.li<{ shown: boolean }>` padding: 0; `; -interface Props { +interface Props extends React.HTMLAttributes<HTMLElement> { shown: boolean; title: string; } -const CompletionTitle: React.FC<React.HTMLAttributes<HTMLElement> & Props> = ( - props -) => <Li {...props}>{props.title}</Li>; +const CompletionTitle: React.FC<Props> = (props) => ( + <Li {...props}>{props.title}</Li> +); export default CompletionTitle; diff --git a/src/console/components/console/Input.tsx b/src/console/components/console/Input.tsx index 448b096..442bd30 100644 --- a/src/console/components/console/Input.tsx +++ b/src/console/components/console/Input.tsx @@ -1,5 +1,5 @@ import React from "react"; -import styled from "../Theme"; +import styled from "../../colorscheme/styled"; const Container = styled.div` background-color: ${({ theme }) => theme.commandBackground}; @@ -19,49 +19,32 @@ const InputInner = styled.input` `; interface Props { - mode: string; + prompt: string; value: string; onBlur: (e: React.FocusEvent<HTMLInputElement>) => void; onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void; onChange: (e: React.ChangeEvent<HTMLInputElement>) => void; } -class Input extends React.Component<Props> { - private input: React.RefObject<HTMLInputElement>; - - constructor(props: Props) { - super(props); - - this.input = React.createRef(); - } - - focus() { - if (this.input.current) { - this.input.current.focus(); - } - } - - render() { - let prompt = ""; - if (this.props.mode === "command") { - prompt = ":"; - } else if (this.props.mode === "find") { - prompt = "/"; - } - - return ( - <Container> - <Prompt>{prompt}</Prompt> - <InputInner - ref={this.input} - onBlur={this.props.onBlur} - onKeyDown={this.props.onKeyDown} - onChange={this.props.onChange} - value={this.props.value} - /> - </Container> - ); - } -} +const Input: React.FC<Props> = (props) => { + const input = React.useRef<HTMLInputElement>(null); + + React.useEffect(() => { + input?.current?.focus(); + }, []); + + return ( + <Container> + <Prompt>{props.prompt}</Prompt> + <InputInner + ref={input} + onBlur={props.onBlur} + onKeyDown={props.onKeyDown} + onChange={props.onChange} + value={props.value} + /> + </Container> + ); +}; export default Input; diff --git a/src/console/components/console/Message.tsx b/src/console/components/console/Message.tsx deleted file mode 100644 index 73498fd..0000000 --- a/src/console/components/console/Message.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from "react"; -import styled from "../Theme"; - -const Error = styled.p` - border-top: 1px solid gray; - background-color: ${({ theme }) => theme.consoleErrorBackground}; - color: ${({ theme }) => theme.consoleErrorForeground}; - font-weight: bold; -`; - -const Info = styled.p` - border-top: 1px solid gray; - background-color: ${({ theme }) => theme.consoleInfoBackground}; - color: ${({ theme }) => theme.consoleInfoForeground}; - font-weight: normal; -`; - -interface Props { - mode: string; - children: string; -} - -const Message: React.FC<Props> = ({ mode, children }) => { - switch (mode) { - case "error": - return <Error role="alert">{children}</Error>; - case "info": - return <Info role="status">{children}</Info>; - } - return null; -}; - -export default Message; |