///
/**
* FilledInput Component - Lynx 版 MUI FilledInput
* 100% 一比一复刻 MUI FilledInput
*
* 带有填充背景的输入框
*
* 对应 MUI: packages/mui-material/src/FilledInput/FilledInput.js
*/
import './FilledInput.css'
import filledInputClasses, { getFilledInputUtilityClass } from './filledInputClasses'
import { InputBase, InputBaseProps } from '../InputBase'
import { useFormControl, formControlState } from '../FormControl'
export { filledInputClasses, getFilledInputUtilityClass }
// =============================================
// 类型定义
// =============================================
export interface FilledInputProps extends InputBaseProps {
/** 是否禁用下划线 */
disableUnderline?: boolean
/** 是否隐藏标签 */
hiddenLabel?: 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 FilledInputProps {
focused?: boolean
}
function useUtilityClasses(ownerState: OwnerState) {
const { classes, disableUnderline, hiddenLabel } = ownerState
const slots = {
root: ['root', !disableUnderline && 'underline', hiddenLabel && 'hiddenLabel'],
input: ['input', hiddenLabel && 'inputHiddenLabel'],
}
return composeClasses(slots, getFilledInputUtilityClass, classes)
}
// =============================================
// FilledInput 组件
// =============================================
export function FilledInput(props: FilledInputProps) {
const {
className,
disableUnderline = false,
fullWidth = false,
hiddenLabel: hiddenLabelProp,
multiline = false,
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 hiddenLabel = hiddenLabelProp ?? fcs.hiddenLabel
const ownerState: OwnerState = {
...props,
color: fcs.color || 'primary',
disabled: fcs.disabled,
disableUnderline,
error: fcs.error,
focused: fcs.focused,
fullWidth,
hiddenLabel,
multiline,
size: fcs.size,
type,
}
// 构建类名
const rootClasses = [
classes.root,
filledInputClasses.root,
className,
!disableUnderline && filledInputClasses.underline,
fcs.focused && filledInputClasses.focused,
fcs.disabled && filledInputClasses.disabled,
fcs.error && filledInputClasses.error,
fcs.size === 'small' && filledInputClasses.sizeSmall,
multiline && filledInputClasses.multiline,
hiddenLabel && filledInputClasses.hiddenLabel,
props.startAdornment && filledInputClasses.adornedStart,
props.endAdornment && filledInputClasses.adornedEnd,
].filter(Boolean).join(' ')
// 输入类名
const inputClasses = [
classes.input,
filledInputClasses.input,
fcs.size === 'small' && filledInputClasses.inputSizeSmall,
multiline && filledInputClasses.inputMultiline,
hiddenLabel && filledInputClasses.inputHiddenLabel,
props.startAdornment && filledInputClasses.inputAdornedStart,
props.endAdornment && filledInputClasses.inputAdornedEnd,
].filter(Boolean).join(' ')
return (
{/* Underline */}
{!disableUnderline && (
)}
)
}
// MUI 名称标识
FilledInput.muiName = 'Input'
export default FilledInput