/// /** * OutlinedInput Component - Lynx 版 MUI OutlinedInput * 100% 一比一复刻 MUI OutlinedInput * * 带有轮廓边框的输入框 * * 对应 MUI: packages/mui-material/src/OutlinedInput/OutlinedInput.js */ import './OutlinedInput.css' import outlinedInputClasses, { getOutlinedInputUtilityClass } from './outlinedInputClasses' import { InputBase, InputBaseProps } from '../InputBase' import { useFormControl, formControlState } from '../FormControl' export { outlinedInputClasses, getOutlinedInputUtilityClass } // ============================================= // 类型定义 // ============================================= export interface OutlinedInputProps extends InputBaseProps { /** 标签(用于计算轮廓缺口) */ label?: any /** 是否显示缺口 */ notched?: boolean } // ============================================= // 辅助函数 // ============================================= function capitalize(str: string): string { return str.charAt(0).toUpperCase() + str.slice(1) } function composeClasses( slots: Record, getUtilityClass: (slot: string) => string, classes?: Record ): Record { const output: Record = {} Object.keys(slots).forEach((slot) => { output[slot] = slots[slot] .filter(Boolean) .map((key) => { if (classes && classes[key as string]) { return `${getUtilityClass(key as string)} ${classes[key as string]}` } return getUtilityClass(key as string) }) .join(' ') }) return output } // ============================================= // useUtilityClasses // ============================================= interface OwnerState extends OutlinedInputProps { focused?: boolean hiddenLabel?: boolean } function useUtilityClasses(ownerState: OwnerState) { const { classes } = ownerState const slots = { root: ['root'], notchedOutline: ['notchedOutline'], input: ['input'], } return composeClasses(slots, getOutlinedInputUtilityClass, classes) } // ============================================= // OutlinedInput 组件 // ============================================= export function OutlinedInput(props: OutlinedInputProps) { const { className, fullWidth = false, label, multiline = false, notched, type = 'text', ...other } = props const classes = useUtilityClasses(props) const muiFormControl = useFormControl() const fcs = formControlState({ props, muiFormControl, states: ['color', 'disabled', 'error', 'focused', 'hiddenLabel', 'size', 'required'], }) const ownerState: OwnerState = { ...props, color: fcs.color || 'primary', disabled: fcs.disabled, error: fcs.error, focused: fcs.focused, fullWidth, hiddenLabel: fcs.hiddenLabel, multiline, size: fcs.size, type, } // 计算是否显示缺口 const showNotch = notched ?? (fcs.focused || fcs.filled || fcs.adornedStart) // 构建类名 const rootClasses = [ classes.root, outlinedInputClasses.root, className, fcs.focused && outlinedInputClasses.focused, fcs.disabled && outlinedInputClasses.disabled, fcs.error && outlinedInputClasses.error, fcs.size === 'small' && outlinedInputClasses.sizeSmall, multiline && outlinedInputClasses.multiline, props.startAdornment && outlinedInputClasses.adornedStart, props.endAdornment && outlinedInputClasses.adornedEnd, ].filter(Boolean).join(' ') // 输入类名 const inputClasses = [ classes.input, outlinedInputClasses.input, fcs.size === 'small' && outlinedInputClasses.inputSizeSmall, multiline && outlinedInputClasses.inputMultiline, props.startAdornment && outlinedInputClasses.inputAdornedStart, props.endAdornment && outlinedInputClasses.inputAdornedEnd, ].filter(Boolean).join(' ') return ( {/* Notched Outline */} {label && showNotch && ( {label} {fcs.required && ' *'} )} ) } // MUI 名称标识 OutlinedInput.muiName = 'Input' export default OutlinedInput