|
@@ -10,6 +10,7 @@ export interface InputProps
|
|
name?: string;
|
|
name?: string;
|
|
hookFormOptions?: RegisterOptions;
|
|
hookFormOptions?: RegisterOptions;
|
|
search?: boolean;
|
|
search?: boolean;
|
|
|
|
+ positiveOnly?: boolean;
|
|
}
|
|
}
|
|
|
|
|
|
const Input: React.FC<InputProps> = ({
|
|
const Input: React.FC<InputProps> = ({
|
|
@@ -18,42 +19,67 @@ const Input: React.FC<InputProps> = ({
|
|
search,
|
|
search,
|
|
inputSize = 'L',
|
|
inputSize = 'L',
|
|
type,
|
|
type,
|
|
|
|
+ positiveOnly,
|
|
...rest
|
|
...rest
|
|
}) => {
|
|
}) => {
|
|
const methods = useFormContext();
|
|
const methods = useFormContext();
|
|
|
|
+ const keyPressEventHandler = (
|
|
|
|
+ event: React.KeyboardEvent<HTMLInputElement>
|
|
|
|
+ ) => {
|
|
|
|
+ const { key, code } = event;
|
|
|
|
+ if (type === 'number') {
|
|
|
|
+ // Manualy prevent input of 'e' character for all number inputs
|
|
|
|
+ // and prevent input of negative numbers for positiveOnly inputs
|
|
|
|
+ if (key === 'e' || (positiveOnly && (key === '-' || code === 'Minus'))) {
|
|
|
|
+ event.preventDefault();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ const pasteEventHandler = (event: React.ClipboardEvent<HTMLInputElement>) => {
|
|
|
|
+ if (type === 'number') {
|
|
|
|
+ const { clipboardData } = event;
|
|
|
|
+ const text = clipboardData.getData('Text');
|
|
|
|
+ // replace all non-digit characters with empty string
|
|
|
|
+ let value = text.replace(/[^\d.]/g, '');
|
|
|
|
+ if (positiveOnly) {
|
|
|
|
+ // check if value is negative
|
|
|
|
+ const parsedData = parseFloat(value);
|
|
|
|
+ if (parsedData < 0) {
|
|
|
|
+ // remove minus sign
|
|
|
|
+ value = String(Math.abs(parsedData));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // if paste value contains non-numeric characters or
|
|
|
|
+ // negative for positiveOnly fields then prevent paste
|
|
|
|
+ if (value !== text) {
|
|
|
|
+ event.preventDefault();
|
|
|
|
+
|
|
|
|
+ // for react-hook-form fields only set transformed value
|
|
|
|
+ if (name) {
|
|
|
|
+ methods.setValue(name, value);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ let inputOptions = { ...rest };
|
|
|
|
+ if (name) {
|
|
|
|
+ // extend input options with react-hook-form options
|
|
|
|
+ // if the field is a part of react-hook-form form
|
|
|
|
+ inputOptions = { ...rest, ...methods.register(name, hookFormOptions) };
|
|
|
|
+ }
|
|
|
|
+
|
|
return (
|
|
return (
|
|
<S.Wrapper>
|
|
<S.Wrapper>
|
|
{search && <SearchIcon />}
|
|
{search && <SearchIcon />}
|
|
- {name ? (
|
|
|
|
- <S.Input
|
|
|
|
- inputSize={inputSize}
|
|
|
|
- {...methods.register(name, { ...hookFormOptions })}
|
|
|
|
- hasLeftIcon={!!search}
|
|
|
|
- type={type}
|
|
|
|
- {...rest}
|
|
|
|
- onKeyDown={(e) => {
|
|
|
|
- if (type === 'number') {
|
|
|
|
- if (e.key === 'e') {
|
|
|
|
- e.preventDefault();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }}
|
|
|
|
- onPaste={(e) => {
|
|
|
|
- if (type === 'number') {
|
|
|
|
- e.preventDefault();
|
|
|
|
- const value = e.clipboardData.getData('Text');
|
|
|
|
- methods.setValue(name, value.replace(/[^\d.]/g, ''));
|
|
|
|
- }
|
|
|
|
- }}
|
|
|
|
- />
|
|
|
|
- ) : (
|
|
|
|
- <S.Input
|
|
|
|
- inputSize={inputSize}
|
|
|
|
- hasLeftIcon={!!search}
|
|
|
|
- type={type}
|
|
|
|
- {...rest}
|
|
|
|
- />
|
|
|
|
- )}
|
|
|
|
|
|
+ <S.Input
|
|
|
|
+ inputSize={inputSize}
|
|
|
|
+ hasLeftIcon={!!search}
|
|
|
|
+ type={type}
|
|
|
|
+ onKeyPress={keyPressEventHandler}
|
|
|
|
+ onPaste={pasteEventHandler}
|
|
|
|
+ {...inputOptions}
|
|
|
|
+ />
|
|
</S.Wrapper>
|
|
</S.Wrapper>
|
|
);
|
|
);
|
|
};
|
|
};
|