import * as React from 'react'; import { Box, FormControl, FormHelperText, FormLabel, IconButton, Input, InputSlotsAndSlotProps } from '@mui/joy'; import KeyIcon from '@mui/icons-material/Key'; import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined'; import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined'; import { getIsMobile } from '~/common/components/useMatchMedia'; import { TooltipOutlined } from '~/common/components/TooltipOutlined'; const slotPropsInputSx: InputSlotsAndSlotProps['slotProps'] = { input: { sx: { width: '100%', }, }, } as const; export function FormInputKey(props: { autoCompleteId: string, // introduced to avoid clashes size?: 'sm' | 'md' | 'lg', label?: string, rightLabel?: string | React.JSX.Element, tooltip?: string, description?: string | React.JSX.Element, value: string, onChange: (value: string) => void, placeholder?: string, initiallyShowKey?: boolean, required: boolean, isError?: boolean, noKey?: boolean, }) { // internal state is only whether the text is visible or not - the actual value is stored in the parent const [isVisible, setIsVisible] = React.useState(!!props.initiallyShowKey); // if mobile, start without autocompletion const disableAutoFocus = getIsMobile(); const handleChange = (e: React.ChangeEvent) => props.onChange((e.target as HTMLInputElement).value); const endDecorator = React.useMemo(() => !!props.value && !props.noKey && ( setIsVisible(!isVisible)}> {isVisible ? : } ), [props.value, props.noKey, isVisible]); const acId = (props.noKey ? 'input-text-' : 'input-key-') + props.autoCompleteId; const ghostUsername = props.noKey ? null : props.autoCompleteId.replace('-key', '').replace('-', ' '); return ( {!!props.label && {props.tooltip ? ( {props.label} ) : ( {props.label} )} {!!props.rightLabel && {props.rightLabel} } } <> {/* Hidden username field to help password managers distinguish between services */} {!!ghostUsername && ( )} } endDecorator={endDecorator} slotProps={slotPropsInputSx} /> {props.description && {props.description}} ); }