Refactor input components

This commit is contained in:
grimsi
2025-06-05 22:53:20 +02:00
parent 7d3bb60321
commit 748a75b675
6 changed files with 52 additions and 48 deletions
@@ -15,27 +15,27 @@ export default function ConfigFormField({configElement, ...props}: any) {
); );
} }
switch (configElement.type) { switch (configElement.type.toLowerCase()) {
case "Boolean": case "boolean":
return ( return (
<CheckboxInput label={configElement.description} name={configElement.key} {...props}/> <CheckboxInput label={configElement.description} name={configElement.key} {...props}/>
); );
case "String": case "string":
return ( return (
<Input label={configElement.description} name={configElement.key} <Input label={configElement.description} name={configElement.key}
type={props.type && "text"} {...props}/> type={props.type && "text"} {...props}/>
); );
case "Float": case "float":
return ( return (
<Input label={configElement.description} name={configElement.key} type="number" <Input label={configElement.description} name={configElement.key} type="number"
step="0.1" {...props}/> step="0.1" {...props}/>
); );
case "Int": case "int":
return ( return (
<Input label={configElement.description} name={configElement.key} type="number" <Input label={configElement.description} name={configElement.key} type="number"
step="1" {...props}/> step="1" {...props}/>
); );
case "Array": case "array":
return ( return (
<ArrayInput label={configElement.description} name={configElement.key} type="text" {...props}/> <ArrayInput label={configElement.description} name={configElement.key} type="text" {...props}/>
); );
@@ -1,8 +1,7 @@
import {FieldArray, useField} from "formik"; import {FieldArray, useField} from "formik";
import {Button, Chip, Input, Popover, PopoverContent, PopoverTrigger} from "@heroui/react"; import {Button, Chip, Input, Popover, PopoverContent, PopoverTrigger} from "@heroui/react";
import {KeyboardEvent, useState} from "react"; import {KeyboardEvent, useState} from "react";
import {Plus, XCircle} from "@phosphor-icons/react"; import {Plus} from "@phosphor-icons/react";
import {SmallInfoField} from "Frontend/components/general/SmallInfoField";
// @ts-ignore // @ts-ignore
const ArrayInput = ({label, ...props}) => { const ArrayInput = ({label, ...props}) => {
@@ -16,7 +15,7 @@ const ArrayInput = ({label, ...props}) => {
function handleKeyDown(event: KeyboardEvent<HTMLInputElement>) { function handleKeyDown(event: KeyboardEvent<HTMLInputElement>) {
if (event.key === "Enter" || event.key == "Tab" || event.key === ",") { if (event.key === "Enter" || event.key == "Tab" || event.key === ",") {
event.preventDefault(); event.preventDefault();
newElementValue newElementValue
.split(",") .split(",")
.map((value) => value.trim()) .map((value) => value.trim())
@@ -58,7 +57,7 @@ const ArrayInput = ({label, ...props}) => {
<div className="min-h-6 text-danger"> <div className="min-h-6 text-danger">
{meta.touched && meta.error && meta.error.trim().length > 0 && ( {meta.touched && meta.error && meta.error.trim().length > 0 && (
<SmallInfoField icon={XCircle} message={meta.error}/> meta.error
)} )}
</div> </div>
</div> </div>
@@ -1,22 +1,28 @@
import {useField} from "formik"; import {useField} from "formik";
import {Checkbox} from "@heroui/react"; import {Checkbox, CheckboxGroup} from "@heroui/react";
// @ts-ignore // @ts-ignore
const CheckboxInput = ({label, ...props}) => { const CheckboxInput = ({label, ...props}) => {
// @ts-ignore // @ts-ignore
const [field] = useField(props); const [field, meta] = useField(props);
return ( return (
<div className="flex flex-row flex-1 items-center gap-2 mb-6"> <CheckboxGroup
className="flex flex-row flex-1 items-baseline gap-2"
isInvalid={!!meta.error}
errorMessage={meta.initialError || meta.error}
value={field.value ? [field.name] : []}
>
<Checkbox <Checkbox
className="items-baseline"
{...field} {...field}
{...props} {...props}
id={field.name} // @ts-ignore
isSelected={field.value} value={field.name}
> >
{label} {label}
</Checkbox> </Checkbox>
</div> </CheckboxGroup>
); );
} }
@@ -1,7 +1,5 @@
import {useField} from "formik"; import {useField} from "formik";
import {Input as NextUiInput} from "@heroui/react"; import {Input as NextUiInput} from "@heroui/react";
import {SmallInfoField} from "Frontend/components/general/SmallInfoField";
import {XCircle} from "@phosphor-icons/react";
// @ts-ignore // @ts-ignore
const Input = ({label, showErrorUntouched = false, ...props}) => { const Input = ({label, showErrorUntouched = false, ...props}) => {
@@ -9,20 +7,15 @@ const Input = ({label, showErrorUntouched = false, ...props}) => {
const [field, meta] = useField(props); const [field, meta] = useField(props);
return ( return (
<div className="flex flex-col flex-1 items-start gap-2"> <NextUiInput
<NextUiInput className="min-h-20"
{...props} {...props}
{...field} {...field}
id={label} id={label}
label={label} label={label}
isInvalid={(meta.touched || showErrorUntouched) && !!meta.error} isInvalid={(meta.touched || showErrorUntouched) && !!meta.error}
/> errorMessage={meta.initialError || meta.error}
<div className="min-h-6 text-danger"> />
{(meta.touched || showErrorUntouched) && meta.error && meta.error.trim().length > 0 && (
<SmallInfoField icon={XCircle} message={meta.error}/>
)}
</div>
</div>
); );
} }
@@ -4,21 +4,26 @@ import {Select, SelectItem} from "@heroui/react";
// @ts-ignore // @ts-ignore
const SelectInput = ({label, values, ...props}) => { const SelectInput = ({label, values, ...props}) => {
// @ts-ignore // @ts-ignore
const [field] = useField(props); const [field, meta] = useField(props);
const items = values.map((v: string) => ({key: v, label: v})); const items = values.map((v: string) => ({key: v, label: v}));
return ( return (
<Select <div>
{...field} <Select
{...props} className="min-h-20"
label={label} {...field}
items={items} {...props}
selectedKeys={[field.value]} label={label}
disallowEmptySelection items={items}
> selectedKeys={[field.value]}
{(item: { key: string, label: string }) => <SelectItem>{item.label}</SelectItem>} isInvalid={!!meta.error}
</Select> errorMessage={meta.initialError || meta.error}
disallowEmptySelection
>
{(item: { key: string, label: string }) => <SelectItem>{item.label}</SelectItem>}
</Select>
</div>
); );
} }
@@ -12,18 +12,19 @@ export default function PluginConfigFormField({pluginConfigMetadata, ...props}:
<SelectInput label={metadata.label} <SelectInput label={metadata.label}
name={metadata.key} name={metadata.key}
values={metadata.allowedValues} values={metadata.allowedValues}
isRequired={metadata.required}
{...props}/> {...props}/>
); );
} }
switch (metadata.type) { switch (metadata.type.toLowerCase()) {
case "Boolean": case "boolean":
return ( return (
<CheckboxInput label={metadata.label} <CheckboxInput label={metadata.label}
name={metadata.key} name={metadata.key}
{...props}/> {...props}/>
); );
case "String": case "string":
return ( return (
<Input label={metadata.label} <Input label={metadata.label}
name={metadata.key} name={metadata.key}
@@ -31,7 +32,7 @@ export default function PluginConfigFormField({pluginConfigMetadata, ...props}:
isRequired={metadata.required} isRequired={metadata.required}
{...props}/> {...props}/>
); );
case "Float": case "float":
return ( return (
<Input label={metadata.label} <Input label={metadata.label}
name={metadata.key} name={metadata.key}
@@ -40,7 +41,7 @@ export default function PluginConfigFormField({pluginConfigMetadata, ...props}:
step="0.1" step="0.1"
{...props}/> {...props}/>
); );
case "Int": case "int":
return ( return (
<Input label={metadata.label} <Input label={metadata.label}
name={metadata.key} name={metadata.key}