diff --git a/packages/web_ui/src/components/InputPartialVersion.tsx b/packages/web_ui/src/components/InputPartialVersion.tsx index 5ec13bb7..022fedaa 100644 --- a/packages/web_ui/src/components/InputPartialVersion.tsx +++ b/packages/web_ui/src/components/InputPartialVersion.tsx @@ -1,5 +1,5 @@ -import React, { useContext, useEffect, useState } from "react"; -import { Button, Divider, Input, TreeSelect } from "antd"; +import React, { useContext, useEffect, useState, useRef } from "react"; +import { Button, Divider, Input, InputRef, RefSelectProps, TreeSelect } from "antd"; import * as lib from "@clusterio/lib"; import { InputComponentProps } from "../BaseWebPlugin"; @@ -17,6 +17,9 @@ export default function InputPartialVersion ( const fieldDefinition = props.fieldDefinition || defaultFieldDefinition; const [versions, setVersions] = useState(lib.ApiVersions); const [customVersion, setCustomVersion] = useState(""); + const [open, setOpen] = useState(false); + const inputRef = useRef(null); + const selectRef = useRef(null); const control = useContext(ControlContext); const account = useAccount(); @@ -58,6 +61,7 @@ export default function InputPartialVersion ( return props.onChange(value ?? null)} value={props.value} @@ -65,30 +69,48 @@ export default function InputPartialVersion ( allowClear={fieldDefinition.optional} className={props.className} disabled={props.disabled} + open={open} + onOpenChange={newOpen => { + setOpen(newOpen); + if (newOpen && typeof props.value === "string") { + setCustomVersion(props.value); + } + }} + onKeyDown={e => { + if (open && e.key === "Tab") { + e.preventDefault(); + inputRef.current?.focus(); + } + }} popupRender={(menu) => { const isValid = lib.isPartialVersion(customVersion); + const submit = () => { + if (customVersion && isValid) { + setTimeout(() => selectRef.current?.focus(), 0); + props.onChange(customVersion); + setOpen(false); + } + }; + return ( <> {menu}
setCustomVersion(e.target.value)} + onPressEnter={submit} /> diff --git a/packages/web_ui/src/components/InputTargetVersion.tsx b/packages/web_ui/src/components/InputTargetVersion.tsx index 85fa4255..13defdea 100644 --- a/packages/web_ui/src/components/InputTargetVersion.tsx +++ b/packages/web_ui/src/components/InputTargetVersion.tsx @@ -1,5 +1,5 @@ -import React, { useContext, useEffect, useState } from "react"; -import { Button, Divider, Input, TreeSelect } from "antd"; +import React, { useContext, useEffect, useState, useRef } from "react"; +import { Button, Divider, Input, InputRef, RefSelectProps, TreeSelect } from "antd"; import * as lib from "@clusterio/lib"; import { InputComponentProps } from "../BaseWebPlugin"; @@ -17,6 +17,9 @@ export default function InputTargetVersion ( const fieldDefinition = props.fieldDefinition || defaultFieldDefinition; const [versions, setVersions] = useState(lib.ApiVersions); const [customVersion, setCustomVersion] = useState(""); + const [open, setOpen] = useState(false); + const inputRef = useRef(null); + const selectRef = useRef(null); const control = useContext(ControlContext); const account = useAccount(); @@ -61,6 +64,7 @@ export default function InputTargetVersion ( return props.onChange(value ?? null)} value={props.value} @@ -68,8 +72,29 @@ export default function InputTargetVersion ( allowClear={fieldDefinition.optional} className={props.className} disabled={props.disabled} + open={open} + onOpenChange={newOpen => { + setOpen(newOpen); + if (newOpen && typeof props.value === "string") { + setCustomVersion(props.value); + } + }} + onKeyDown={e => { + if (open && e.key === "Tab") { + e.preventDefault(); + inputRef.current?.focus(); + } + }} popupRender={(menu) => { - const isValid = lib.isPartialVersion(customVersion); + const isValid = lib.isTargetVersion(customVersion); + + const submit = () => { + if (customVersion && isValid) { + setTimeout(() => selectRef.current?.focus(), 0); + props.onChange(customVersion); + setOpen(false); + } + }; return ( <> @@ -77,21 +102,18 @@ export default function InputTargetVersion (
setCustomVersion(e.target.value)} + onPressEnter={submit} />