import Clear from '@mui/icons-material/Clear' import Visibility from '@mui/icons-material/Visibility' import VisibilityOff from '@mui/icons-material/VisibilityOff' import { IconButton, InputAdornment, TextField } from '@mui/material' import { useState, type KeyboardEvent, type MouseEvent, type ReactNode } from 'react' import { verbatim } from './fonts.ts' /** Keeps the focus in the input when one of its buttons is pressed. */ function keepFocus(event: MouseEvent) { event.preventDefault() } /** * A text field with a clear button, a show/hide button for secrets, and several lines for 'lines'. The browser * may not change what is typed (no spell check, capitalisation or completion). A small field shows no label; the * label remains its accessible name. */ export default function TextInput(props: { label: string value: string kind?: 'text' | 'secret' | 'lines' problem?: string help?: string disabled?: boolean autoFocus?: boolean start?: ReactNode size?: 'small' | 'medium' onChange: (value: string) => void onBlur?: () => void onKeyDown?: (event: KeyboardEvent) => void }) { const { label, value, kind = 'text', problem, help, disabled = false, onChange } = props const [shown, setShown] = useState(false) return ( onChange(event.target.value)} slotProps={{ htmlInput: { ...verbatim, 'aria-label': label }, input: { startAdornment: props.start === undefined ? undefined : {props.start}, endAdornment: ( {kind === 'secret' && ( setShown(!shown)} onMouseDown={keepFocus} onMouseUp={keepFocus}> {shown ? : } )} {value !== '' && ( onChange('')} onMouseDown={keepFocus} onMouseUp={keepFocus}> )} ), }, }} /> ) }