u
This commit is contained in:
139
src/components/TextInput.jsx
Normal file
139
src/components/TextInput.jsx
Normal file
@@ -0,0 +1,139 @@
|
||||
import { Component } from 'react';
|
||||
import TextField from '@mui/material/TextField';
|
||||
|
||||
function normalizeSx(s) {
|
||||
if (!s || typeof s !== 'object' || Array.isArray(s)) return s;
|
||||
const bg = s.bgcolor ?? s.backgroundColor;
|
||||
if (bg && bg !== 'transparent') {
|
||||
const { bgcolor: _bg, backgroundColor: _bgc, ...rest } = s;
|
||||
return {
|
||||
...rest,
|
||||
bgcolor: 'transparent',
|
||||
'& .MuiInputBase-root': {
|
||||
bgcolor: bg,
|
||||
...(typeof rest['& .MuiInputBase-root'] === 'object' ? rest['& .MuiInputBase-root'] : {}),
|
||||
},
|
||||
};
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function resolveSx(s) {
|
||||
if (!s) return undefined;
|
||||
if (Array.isArray(s)) return s.map(resolveSx);
|
||||
return normalizeSx(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* TextInput:
|
||||
* Reusable Class Component wrapping MUI TextField with the harmonized
|
||||
* style of EANs (small outlined, shrink label by default, transparent root)
|
||||
* and complete suppression of browser autocomplete/autofill popups.
|
||||
*/
|
||||
export default class TextInput extends Component {
|
||||
state = {
|
||||
// Starting as readOnly prevents Chrome/Safari/Firefox from attaching autofill popup listeners
|
||||
readOnly: true,
|
||||
};
|
||||
|
||||
handleFocus = (e) => {
|
||||
if (this.state.readOnly && !this.props.readOnly && !this.props.slotProps?.htmlInput?.readOnly) {
|
||||
this.setState({ readOnly: false });
|
||||
}
|
||||
if (this.props.onFocus) {
|
||||
this.props.onFocus(e);
|
||||
}
|
||||
};
|
||||
|
||||
handleMouseDown = (e) => {
|
||||
if (this.state.readOnly && !this.props.readOnly && !this.props.slotProps?.htmlInput?.readOnly) {
|
||||
this.setState({ readOnly: false });
|
||||
}
|
||||
if (this.props.onMouseDown) {
|
||||
this.props.onMouseDown(e);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
slotProps,
|
||||
inputProps,
|
||||
InputProps,
|
||||
InputLabelProps,
|
||||
inputRef,
|
||||
label,
|
||||
size = 'small',
|
||||
onFocus,
|
||||
onMouseDown,
|
||||
readOnly: propReadOnly,
|
||||
sx,
|
||||
...rest
|
||||
} = this.props;
|
||||
|
||||
const isSelect = Boolean(rest.select);
|
||||
const effectiveReadOnly = isSelect
|
||||
? (propReadOnly ?? slotProps?.htmlInput?.readOnly ?? inputProps?.readOnly)
|
||||
: (propReadOnly ?? slotProps?.htmlInput?.readOnly ?? inputProps?.readOnly ?? this.state.readOnly);
|
||||
|
||||
const htmlInput = isSelect
|
||||
? {
|
||||
readOnly: effectiveReadOnly,
|
||||
...slotProps?.htmlInput,
|
||||
...inputProps,
|
||||
}
|
||||
: {
|
||||
autoComplete: 'one-time-code',
|
||||
autoCorrect: 'off',
|
||||
autoCapitalize: 'off',
|
||||
spellCheck: false,
|
||||
'aria-autocomplete': 'none',
|
||||
'data-lpignore': 'true',
|
||||
'data-1p-ignore': 'true',
|
||||
'data-bwignore': 'true',
|
||||
'data-form-type': 'other',
|
||||
readOnly: effectiveReadOnly,
|
||||
...slotProps?.htmlInput,
|
||||
...inputProps,
|
||||
};
|
||||
|
||||
const resolvedInputProps = (InputProps || slotProps?.input) ? {
|
||||
...slotProps?.input,
|
||||
...InputProps,
|
||||
startAdornment: (slotProps?.input?.startAdornment && InputProps?.startAdornment)
|
||||
? <>{slotProps.input.startAdornment}{InputProps.startAdornment}</>
|
||||
: (InputProps?.startAdornment ?? slotProps?.input?.startAdornment),
|
||||
endAdornment: (slotProps?.input?.endAdornment && InputProps?.endAdornment)
|
||||
? <>{InputProps.endAdornment}{slotProps.input.endAdornment}</>
|
||||
: (InputProps?.endAdornment ?? slotProps?.input?.endAdornment),
|
||||
} : undefined;
|
||||
|
||||
const { input: _unusedInput, ...restSlotProps } = (slotProps || {});
|
||||
|
||||
const mergedSlotProps = {
|
||||
...restSlotProps,
|
||||
inputLabel: {
|
||||
...(label ? { shrink: true } : {}),
|
||||
...InputLabelProps,
|
||||
...slotProps?.inputLabel,
|
||||
},
|
||||
htmlInput,
|
||||
};
|
||||
|
||||
return (
|
||||
<TextField
|
||||
size={size}
|
||||
label={label}
|
||||
inputRef={inputRef}
|
||||
autoComplete="one-time-code"
|
||||
onFocus={this.handleFocus}
|
||||
onMouseDown={this.handleMouseDown}
|
||||
InputProps={resolvedInputProps}
|
||||
slotProps={mergedSlotProps}
|
||||
sx={resolveSx(sx)}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { TextInput };
|
||||
Reference in New Issue
Block a user