/// /** * InputAdornment Component - Lynx 版 MUI InputAdornment * 100% 一比一复刻 MUI InputAdornment * * 用于在 Input 前后添加装饰元素(如图标、按钮、文本等) * * 对应 MUI: packages/mui-material/src/InputAdornment/InputAdornment.js */ import './InputAdornment.css' import inputAdornmentClasses, { getInputAdornmentUtilityClass } from './inputAdornmentClasses' import { useFormControl, formControlState } from '../FormControl' export { inputAdornmentClasses, getInputAdornmentUtilityClass } // ============================================= // 类型定义 // ============================================= export type InputAdornmentPosition = 'start' | 'end' export type InputAdornmentVariant = 'standard' | 'outlined' | 'filled' export interface InputAdornmentProps { /** 子元素 */ children?: any /** 自定义类名 */ className?: string /** 样式类覆盖 */ classes?: Partial /** 是否禁用指针事件 */ disablePointerEvents?: boolean /** 是否禁用排版 */ disableTypography?: boolean /** 位置 */ position: InputAdornmentPosition /** 内联样式 */ style?: Record /** sx 属性 */ sx?: Record /** 变体 */ variant?: InputAdornmentVariant } // ============================================= // 辅助函数 // ============================================= 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 InputAdornmentProps { hiddenLabel?: boolean size?: string } function useUtilityClasses(ownerState: OwnerState) { const { classes, disablePointerEvents, hiddenLabel, position, size, variant } = ownerState const slots = { root: [ 'root', disablePointerEvents && 'disablePointerEvents', position && `position${capitalize(position)}`, variant, hiddenLabel && 'hiddenLabel', size === 'small' && 'sizeSmall', ], } return composeClasses(slots, getInputAdornmentUtilityClass, classes) } // ============================================= // InputAdornment 组件 // ============================================= export function InputAdornment(props: InputAdornmentProps) { const { children, className, classes: classesProp, disablePointerEvents = false, disableTypography = false, position, style, sx, variant: variantProp, ...other } = props const muiFormControl = useFormControl() const variant = variantProp || (muiFormControl ? muiFormControl.variant : 'outlined') const ownerState: OwnerState = { ...props, disablePointerEvents, hiddenLabel: muiFormControl?.hiddenLabel, size: muiFormControl?.size, variant, } const classes = useUtilityClasses(ownerState) // 构建类名 const rootClasses = [ classes.root, className, ].filter(Boolean).join(' ') // 渲染子元素 let content = children if (typeof children === 'string' && !disableTypography) { content = {children} } return ( {content} ) } export default InputAdornment