Files
optolith-client/src/shared/components/basicInputDialog/BasicInputDialog.tsx
T
2024-09-05 14:37:55 +02:00

104 lines
2.2 KiB
TypeScript

import { FC, useCallback, useEffect } from "react"
import { addKeybinding, removeKeybinding } from "../../utils/keybindings.ts"
import { Dialog } from "../dialog/Dialog.tsx"
import { InputKeyEvent, TextField } from "../textField/TextField.tsx"
type Props = {
id: string
isOpen: boolean
title: string
description: string
value: string | undefined
invalid?: string
acceptLabel: string
rejectLabel: string
rejectDisabled?: boolean
onClose: () => void
onAccept: () => void
onReject?: () => void
onChange: (newText: string) => void
}
/**
* A dialog with a single text field.
*/
export const BasicInputDialog: FC<Props> = props => {
const {
id,
isOpen,
title,
description,
value,
invalid,
acceptLabel,
rejectLabel,
rejectDisabled = false,
onClose,
onAccept,
onReject = () => undefined,
onChange,
} = props
const isInputEmpty = value === undefined || value === ""
const acceptDisabled = isInputEmpty || invalid !== undefined
const handleKeyUp = useCallback(
(event: InputKeyEvent) => {
if (event.key === "Enter" && !acceptDisabled) {
onAccept()
onClose()
} else if (event.key === "Enter" && isInputEmpty && !rejectDisabled) {
onReject()
onClose()
} else if (event.key === "Escape") {
onClose()
}
},
[acceptDisabled, isInputEmpty, rejectDisabled, onAccept, onReject, onClose],
)
useEffect(() => {
addKeybinding("esc", () => {
onClose()
})
return () => {
removeKeybinding("esc")
}
})
return (
<Dialog
id={id}
close={onClose}
isOpen={isOpen}
title={title}
buttons={[
{
autoWidth: true,
label: acceptLabel,
disabled: acceptDisabled,
onClick: onAccept,
},
{
autoWidth: true,
label: rejectLabel,
disabled: rejectDisabled,
onClick: onReject,
},
]}
>
<p className="description">{description}</p>
<TextField
value={value}
onChange={onChange}
fullWidth
autoFocus
error={invalid}
onKeyUp={handleKeyUp}
/>
</Dialog>
)
}