///
/**
* 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