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