-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathInput.tsx
More file actions
111 lines (103 loc) · 3.61 KB
/
Input.tsx
File metadata and controls
111 lines (103 loc) · 3.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/* eslint-disable complexity */
import { FieldValues } from "react-hook-form";
import { FormGroup, Label } from "reactstrap";
import { InputType } from "reactstrap/types/lib/Input";
import { useSafeNameId } from "src/lib/hooks/useSafeNameId";
import { FormGroupLayout } from "./FormGroupLayout";
import { InputInternal } from "./InputInternal";
import { CommonInputProps } from "./types/CommonInputProps";
import { LabelValueOption } from "./types/LabelValueOption";
import { UnknownType, useFormContextInternal } from "./context/FormContext";
import { MutableRefObject } from "react";
const invalidAddonTypes = ["switch", "radio", "checkbox"];
type InputProps<T extends FieldValues = UnknownType> = CommonInputProps<T> & {
type?: InputType;
options?: LabelValueOption[];
multiple?: boolean;
value?: string | number;
rangeMin?: number;
rangeMax?: number;
textAreaRows?: number;
plainText?: boolean;
placeholder?: string;
step?: number;
innerRef?: MutableRefObject<HTMLInputElement | HTMLTextAreaElement | null>;
}
const Input = <T extends FieldValues = UnknownType>(props: InputProps<T>) => {
const { type, options, addonLeft, name, addonRight, rangeMin, rangeMax, textAreaRows, multiple, id, value, disabled, step } = props;
if (type === "radio" && !options) {
throw new Error("options must be provided for radio inputs");
}
if (type === "select" && !options) {
throw new Error("options must be provided for select inputs");
}
if ((addonLeft || addonRight) && type && invalidAddonTypes.includes(type)) {
throw new Error("Addons can not be shown on switch, radio or checkbox types of inputs");
}
if (multiple && type !== "select") {
throw new Error("multiple can only be used with select inputs");
}
if ((rangeMin || rangeMax) && type !== "range") {
throw new Error("rangeMin and rangeMax can only be used with range inputs");
}
if (textAreaRows && type !== "textarea") {
throw new Error("textAreaRows can only be used with textarea inputs");
}
if (value && type === "radio") {
throw new Error("value can only be used with radio inputs");
}
if (options && options.filter((option) => option.value === undefined).length > 1) {
throw new Error("options can only contain one undefined value");
}
if (step && type !== "number" && type !== "range") {
throw new Error("step can only be used with number or range inputs");
}
const formGroupLayout = (() => {
if (type === "switch") {
return "switch";
}
if (type === "checkbox") {
return "checkbox";
}
return undefined;
})();
const { id: safeId } = useSafeNameId(name ?? "", id);
const { disabled: formDisabled = false } = useFormContextInternal<T>() ?? {};
const isDisabled = formDisabled || disabled;
return (
<FormGroupLayout
{...props}
layout={formGroupLayout}
addonProps={{
isDisabled,
}}
>
{type === "radio" ? (
<>
{options?.map((option, i) => {
const optionId = `${safeId}-${i}`;
return (
<FormGroup key={option.value} check>
<InputInternal
{...props}
id={optionId}
value={option.value}
options={undefined}
disabled={isDisabled || option?.disabled}
/>
<Label for={optionId} check>
{option.label}
</Label>
</FormGroup>
);
})}
</>
) : (
<>
<InputInternal {...props as InputProps} />
</>
)}
</FormGroupLayout>
);
};
export { Input, InputProps };