198 lines
3.7 KiB
TypeScript
198 lines
3.7 KiB
TypeScript
import {
|
|
Checkbox,
|
|
CheckboxProps,
|
|
Chip,
|
|
ChipProps,
|
|
Fieldset,
|
|
FieldsetProps,
|
|
MultiSelect,
|
|
MultiSelectProps,
|
|
NumberInput,
|
|
NumberInputProps,
|
|
PasswordInput,
|
|
PasswordInputProps,
|
|
Select,
|
|
SelectProps,
|
|
TextInput,
|
|
TextInputProps,
|
|
Textarea,
|
|
TextareaProps,
|
|
} from "@mantine/core";
|
|
import { ReactNode } from "@tanstack/react-router";
|
|
|
|
type GeneralInputProps = {
|
|
hidden?: boolean;
|
|
key?: string | number;
|
|
};
|
|
|
|
type TextInputType = {
|
|
type: "text";
|
|
} & TextInputProps;
|
|
|
|
type MultiSelectInputType = {
|
|
type: "multi-select";
|
|
} & MultiSelectProps;
|
|
|
|
type PasswordInputType = {
|
|
type: "password";
|
|
} & PasswordInputProps;
|
|
|
|
type NumberInputType = {
|
|
type: "number";
|
|
} & Omit<NumberInputProps, "type">;
|
|
|
|
type SelectType = {
|
|
type: "select";
|
|
} & SelectProps;
|
|
|
|
type Group = {
|
|
type: "group";
|
|
inputs: AcceptedInput[];
|
|
} & FieldsetProps;
|
|
|
|
type ChipType = {
|
|
type: "chip";
|
|
} & Omit<ChipProps, "type">;
|
|
|
|
type CheckboxType = {
|
|
type: "checkbox";
|
|
} & CheckboxProps;
|
|
|
|
type TextareaType = {
|
|
type: "textarea";
|
|
} & TextareaProps;
|
|
|
|
type AcceptedInput = (
|
|
| TextInputType
|
|
| MultiSelectInputType
|
|
| PasswordInputType
|
|
| NumberInputType
|
|
| SelectType
|
|
| ChipType
|
|
| Group
|
|
| CheckboxType
|
|
| TextareaType
|
|
) &
|
|
GeneralInputProps;
|
|
|
|
interface Options {
|
|
disableAll?: boolean;
|
|
readonlyAll?: boolean;
|
|
inputs: AcceptedInput[];
|
|
}
|
|
|
|
function createInputComponents(options: Options) {
|
|
const components = [] as ReactNode[];
|
|
|
|
const createComponent = ({ key, ...input }: AcceptedInput) => {
|
|
switch (input.type) {
|
|
case "text":
|
|
return (
|
|
<TextInput
|
|
{...input}
|
|
key={key}
|
|
readOnly={options.readonlyAll || input.readOnly}
|
|
disabled={options.disableAll || input.disabled}
|
|
/>
|
|
);
|
|
case "multi-select":
|
|
return (
|
|
<MultiSelect
|
|
{...input}
|
|
key={key}
|
|
readOnly={options.readonlyAll || input.readOnly}
|
|
disabled={options.disableAll || input.disabled}
|
|
/>
|
|
);
|
|
case "password":
|
|
return (
|
|
<PasswordInput
|
|
{...input}
|
|
key={key}
|
|
readOnly={options.readonlyAll || input.readOnly}
|
|
disabled={options.disableAll || input.disabled}
|
|
/>
|
|
);
|
|
case "number":
|
|
return (
|
|
<NumberInput
|
|
{...input}
|
|
key={key}
|
|
type="text"
|
|
readOnly={options.readonlyAll || input.readOnly}
|
|
disabled={options.disableAll || input.disabled}
|
|
/>
|
|
);
|
|
case "select":
|
|
return (
|
|
<Select
|
|
{...input}
|
|
key={key}
|
|
readOnly={options.readonlyAll || input.readOnly}
|
|
disabled={options.disableAll || input.disabled}
|
|
/>
|
|
);
|
|
|
|
case "group": {
|
|
const localComponents: ReactNode[] = [];
|
|
|
|
for (const [key, child] of input.inputs.entries()) {
|
|
if (child.hidden) continue;
|
|
|
|
localComponents.push(createComponent({ ...child, key }));
|
|
}
|
|
|
|
return (
|
|
<Fieldset key={key} {...input}>
|
|
{localComponents}
|
|
</Fieldset>
|
|
);
|
|
}
|
|
|
|
case "chip": {
|
|
return (
|
|
<Chip
|
|
{...input}
|
|
key={key}
|
|
type="checkbox"
|
|
readOnly={options.readonlyAll || input.readOnly}
|
|
disabled={options.disableAll || input.disabled}
|
|
/>
|
|
);
|
|
}
|
|
|
|
case "checkbox": {
|
|
return (
|
|
<Checkbox
|
|
{...input}
|
|
key={key}
|
|
readOnly={options.readonlyAll || input.readOnly}
|
|
disabled={options.disableAll || input.disabled}
|
|
/>
|
|
);
|
|
}
|
|
|
|
case "textarea": {
|
|
return (
|
|
<Textarea
|
|
{...input}
|
|
key={key}
|
|
readOnly={options.readonlyAll || input.readOnly}
|
|
disabled={options.disableAll || input.disabled}
|
|
/>
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
for (const [index, input] of options.inputs.entries()) {
|
|
if (input.hidden) continue;
|
|
|
|
components.push(createComponent({ ...input, key: index }));
|
|
}
|
|
|
|
return <>{components}</>;
|
|
}
|
|
|
|
export default createInputComponents;
|