import { FC, useCallback, useMemo, useState } from 'react'; import { QuestionMark as MUIQuestionMarkIcon } from '@mui/icons-material'; import { FormControl as MUIFormControl, FormControlProps as MUIFormControlProps, IconButton as MUIIconButton, IconButtonProps as MUIIconButtonProps, iconButtonClasses as muiIconButtonClasses, InputAdornment as MUIInputAdornment, } from '@mui/material'; import { GREY } from '../lib/consts/DEFAULT_THEME'; import InputMessageBox from './InputMessageBox'; import { MessageBoxProps } from './MessageBox'; import OutlinedInput, { OutlinedInputProps } from './OutlinedInput'; import OutlinedInputLabel, { OutlinedInputLabelProps, } from './OutlinedInputLabel'; type OutlinedInputWithLabelOptionalProps = { fillRow?: boolean; formControlProps?: Partial; helpMessageBoxProps?: Partial; id?: string; inputProps?: Partial; inputLabelProps?: Partial; messageBoxProps?: Partial; onChange?: OutlinedInputProps['onChange']; onHelp?: MUIIconButtonProps['onClick']; onHelpAppend?: MUIIconButtonProps['onClick']; required?: boolean; value?: OutlinedInputProps['value']; }; type OutlinedInputWithLabelProps = { label: string; } & OutlinedInputWithLabelOptionalProps; const OUTLINED_INPUT_WITH_LABEL_DEFAULT_PROPS: Required< Omit< OutlinedInputWithLabelOptionalProps, 'onChange' | 'onHelp' | 'onHelpAppend' > > & Pick< OutlinedInputWithLabelOptionalProps, 'onChange' | 'onHelp' | 'onHelpAppend' > = { fillRow: false, formControlProps: {}, helpMessageBoxProps: {}, id: '', inputProps: {}, inputLabelProps: {}, messageBoxProps: {}, onChange: undefined, onHelp: undefined, onHelpAppend: undefined, required: false, value: '', }; const OutlinedInputWithLabel: FC = ({ fillRow: isFillRow = OUTLINED_INPUT_WITH_LABEL_DEFAULT_PROPS.fillRow, formControlProps = OUTLINED_INPUT_WITH_LABEL_DEFAULT_PROPS.formControlProps, helpMessageBoxProps = OUTLINED_INPUT_WITH_LABEL_DEFAULT_PROPS.helpMessageBoxProps, id = OUTLINED_INPUT_WITH_LABEL_DEFAULT_PROPS.id, inputProps: { endAdornment, ...restInputProps } = OUTLINED_INPUT_WITH_LABEL_DEFAULT_PROPS.inputProps, inputLabelProps = OUTLINED_INPUT_WITH_LABEL_DEFAULT_PROPS.inputLabelProps, label, messageBoxProps = OUTLINED_INPUT_WITH_LABEL_DEFAULT_PROPS.messageBoxProps, onChange, onHelp, onHelpAppend, required = OUTLINED_INPUT_WITH_LABEL_DEFAULT_PROPS.required, value = OUTLINED_INPUT_WITH_LABEL_DEFAULT_PROPS.value, }) => { const { sx: formControlSx, ...restFormControlProps } = formControlProps; const { text: helpText = '' } = helpMessageBoxProps; const [isShowHelp, setIsShowHelp] = useState(false); const formControlWidth = useMemo( () => (isFillRow ? '100%' : undefined), [isFillRow], ); const isShowHelpButton: boolean = useMemo( () => onHelp !== undefined || helpText.length > 0, [helpText, onHelp], ); const createHelpHandler = useCallback< () => MUIIconButtonProps['onClick'] >(() => { let handler: MUIIconButtonProps['onClick']; if (onHelp) { handler = onHelp; } else if (helpText.length > 0) { handler = (...args) => { setIsShowHelp((previous) => !previous); onHelpAppend?.call(null, ...args); }; } return handler; }, [helpText, onHelp, onHelpAppend]); const handleHelp = useMemo(createHelpHandler, [createHelpHandler]); return ( {label} .${muiIconButtonClasses.root}`]: { color: GREY, padding: '.2em', }, [`& > :not(:first-child, .${muiIconButtonClasses.root})`]: { marginLeft: '.3em', }, }} > {endAdornment} {isShowHelpButton && ( )} ), fullWidth: formControlProps.fullWidth, id, label, onChange, value, ...restInputProps, }} /> {isShowHelp && ( { setIsShowHelp(false); }, ...helpMessageBoxProps, }} /> )} ); }; OutlinedInputWithLabel.defaultProps = OUTLINED_INPUT_WITH_LABEL_DEFAULT_PROPS; export type { OutlinedInputWithLabelProps }; export default OutlinedInputWithLabel;