feature: sk-react-toolkit holds the server helpers, web components and Vite font plugin shared by manage-ui and sql-query-webui.
Release / release (push) Failing after 1m18s
Release / release (push) Failing after 1m18s
This commit is contained in:
commit
4505b37abc
30 files changed
+4826
No files matched your search
@@ -0,0 +1,72 @@
|
||||
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<HTMLButtonElement>) {
|
||||
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<HTMLDivElement>) => void
|
||||
}) {
|
||||
const { label, value, kind = 'text', problem, help, disabled = false, onChange } = props
|
||||
const [shown, setShown] = useState(false)
|
||||
return (
|
||||
<TextField
|
||||
label={props.size === 'small' ? undefined : label}
|
||||
value={value}
|
||||
size={props.size ?? (kind === 'lines' ? 'medium' : undefined)}
|
||||
fullWidth
|
||||
onBlur={props.onBlur}
|
||||
onKeyDown={props.onKeyDown}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={disabled}
|
||||
error={problem !== undefined}
|
||||
helperText={props.size === 'small' ? problem : problem || help || ' '}
|
||||
multiline={kind === 'lines'}
|
||||
minRows={kind === 'lines' ? 2 : undefined}
|
||||
type={kind === 'secret' && !shown ? 'password' : 'text'}
|
||||
onChange={(event) => onChange(event.target.value)}
|
||||
slotProps={{
|
||||
htmlInput: { ...verbatim, 'aria-label': label },
|
||||
input: {
|
||||
startAdornment: props.start === undefined ? undefined : <InputAdornment position="start">{props.start}</InputAdornment>,
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
{kind === 'secret' && (
|
||||
<IconButton aria-label={shown ? `hide ${label}` : `show ${label}`} disabled={disabled} onClick={() => setShown(!shown)} onMouseDown={keepFocus} onMouseUp={keepFocus}>
|
||||
{shown ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
)}
|
||||
{value !== '' && (
|
||||
<IconButton aria-label={`clear ${label}`} disabled={disabled} edge="end" onClick={() => onChange('')} onMouseDown={keepFocus} onMouseUp={keepFocus}>
|
||||
<Clear />
|
||||
</IconButton>
|
||||
)}
|
||||
</InputAdornment>
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user