Skip to content

Commit 281aa5a

Browse files
committed
rework of form wrapper elements
1 parent f246355 commit 281aa5a

File tree

6 files changed

+192
-173
lines changed

6 files changed

+192
-173
lines changed

library/src/components/form/DynamicForm.tsx

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,32 @@
1-
import React from "react"
21
import {
3-
Control,
4-
DefaultValues,
5-
FieldValues,
6-
RegisterOptions,
7-
useForm,
8-
UseFormRegisterReturn,
9-
UseFormWatch,
2+
type Path,
3+
useForm,
4+
type Control,
5+
type DefaultValues,
6+
type FieldValues,
7+
type RegisterOptions,
8+
type UseFormRegisterReturn,
9+
type UseFormWatch,
1010
} from "react-hook-form"
11-
import {twMerge} from "tailwind-merge";
12-
import {Button} from "../Button";
11+
import { twMerge } from "tailwind-merge"
12+
import { Button } from "../Button"
1313

1414
export interface FormProps<T extends FieldValues> {
15-
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
16-
control: Control<T, any>
15+
control: Control<T>
1716
watch: UseFormWatch<T>
18-
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
1917
register: (
20-
name: any,
21-
options?: RegisterOptions<T, any> | undefined,
22-
) => UseFormRegisterReturn<any>
18+
name: Path<T>,
19+
options?: RegisterOptions<T>,
20+
) => UseFormRegisterReturn
2321
readonly?: boolean
2422
}
2523

2624
export interface FormField<T extends FieldValues> {
27-
objKey: keyof T
25+
name: Path<T>
2826
title: string
2927
description?: string
3028
required?: boolean
31-
formProps?: FormProps<T>
29+
formProps: FormProps<T>
3230
}
3331

3432
export interface DynamicFormProps<T extends FieldValues>
@@ -97,7 +95,7 @@ export function DynamicForm<T extends FieldValues>({
9795

9896
<hr className="border border-border" />
9997

100-
<div className={`flex flex-row items-end w-full justify-end mt-4`}>
98+
<div className="flex flex-row items-end w-full justify-end mt-4">
10199
{!hideReset && (
102100
<Button
103101
type="reset"

library/src/components/form/elements/CheckboxFormField.tsx

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,49 @@
1-
import React, {useEffect} from "react"
2-
import {FieldValues, Path} from "react-hook-form"
3-
import {FormField} from "../DynamicForm";
4-
import {Label} from "../../inputs";
5-
import {Checkbox} from "../../Checkbox";
1+
import { useEffect, useRef } from "react"
2+
import type { FieldValues } from "react-hook-form"
3+
import type { FormField } from "../DynamicForm"
4+
import { Label } from "../../inputs"
5+
import { Checkbox } from "../../Checkbox"
66

7-
export interface CheckboxFormField<T extends FieldValues>
8-
extends FormField<T> {
7+
export interface CheckboxFormField<T extends FieldValues> extends FormField<T> {
98
onChange?: (value: string) => void
109
}
1110

12-
export function CheckboxFormField<T extends FieldValues>(
13-
props: CheckboxFormField<T>,
14-
) {
15-
console.info("formProps", props.formProps)
16-
const fieldValue = props.formProps?.watch(props.objKey as Path<T>)
11+
export function CheckboxFormField<T extends FieldValues>({
12+
name,
13+
onChange,
14+
formProps,
15+
required,
16+
description,
17+
title,
18+
}: CheckboxFormField<T>) {
19+
const fieldValue = formProps.watch(name)
20+
const onChangeCB = useRef(onChange)
21+
if (onChangeCB.current !== onChange) {
22+
onChangeCB.current = onChange
23+
}
1724

18-
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
1925
useEffect(() => {
20-
if (props.onChange) {
21-
// @ts-ignore
22-
props.onChange(fieldValue)
23-
}
26+
onChangeCB.current?.(fieldValue)
2427
}, [fieldValue])
2528

26-
const inputProps = props.formProps?.register(props.objKey)
29+
const inputProps = formProps.register(name)
2730

2831
return (
2932
<div className="flex flex-1 flex-col">
30-
<Label
31-
htmlFor={inputProps?.name}
32-
required={props.required}
33-
>
34-
{props.title}
33+
<Label htmlFor={name} required={required}>
34+
{title}
3535
</Label>
36-
{props.description && (
36+
{description && (
3737
<p className="mt-0 pb-2">
38-
<small>{props.description}</small>
38+
<small>{description}</small>
3939
</p>
4040
)}
4141
<Checkbox
4242
className="mt-2"
4343
label={"Aktivieren"}
44-
disabled={props.formProps?.readonly === true}
44+
disabled={formProps.readonly}
4545
id={inputProps?.name}
4646
{...inputProps}
47-
onChange={(event) => {
48-
if (props.onChange) {
49-
props.onChange(
50-
// @ts-ignore
51-
(event.target as HTMLInputElement).checked,
52-
)
53-
}
54-
}}
5547
/>
5648
</div>
5749
)

library/src/components/form/elements/InputFormField.tsx

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,49 @@
1-
import React, {useEffect} from "react"
2-
import {FieldValues, Path} from "react-hook-form"
3-
import {FormField} from "../DynamicForm";
4-
import {Input, Label} from "../../inputs";
1+
import { useEffect, useRef } from "react"
2+
import type { FieldValues } from "react-hook-form"
3+
import type { FormField } from "../DynamicForm"
4+
import { Input, Label } from "../../inputs"
55

6-
export interface InputFormField<T extends FieldValues>
7-
extends FormField<T> {
6+
export interface InputFormField<T extends FieldValues> extends FormField<T> {
87
onChange?: (value: string) => void
8+
placeholder?: string
99
}
1010

11-
export function InputFormField<T extends FieldValues>(
12-
props: InputFormField<T>,
13-
) {
14-
console.info("formProps", props.formProps)
15-
const fieldValue = props.formProps?.watch(props.objKey as Path<T>)
11+
export function InputFormField<T extends FieldValues>({
12+
onChange,
13+
formProps,
14+
name,
15+
required,
16+
description,
17+
title,
18+
placeholder,
19+
}: InputFormField<T>) {
20+
const fieldValue = formProps.watch(name)
21+
const onChangeCB = useRef(onChange)
22+
if (onChangeCB.current !== onChange) {
23+
onChangeCB.current = onChange
24+
}
1625

17-
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
1826
useEffect(() => {
19-
if (props.onChange) {
20-
// @ts-ignore
21-
props.onChange(fieldValue)
22-
}
27+
onChangeCB.current?.(fieldValue)
2328
}, [fieldValue])
2429

25-
const inputProps = props.formProps?.register(props.objKey)
30+
const inputProps = formProps.register(name)
2631

2732
return (
28-
<div className="flex flex-1 flex-col">
29-
<Label
30-
htmlFor={inputProps?.name}
31-
required={props.required}
32-
>
33-
{props.title}
33+
<div className="flex flex-1 flex-col min-w-max">
34+
<Label htmlFor={name} required={required}>
35+
{title}
3436
</Label>
35-
{props.description && (
37+
{description && (
3638
<p className="mt-0 pb-2">
37-
<small>{props.description}</small>
39+
<small>{description}</small>
3840
</p>
3941
)}
4042
<Input
41-
id={inputProps?.name}
42-
{...(inputProps as React.InputHTMLAttributes<HTMLInputElement>)}
43-
disabled={props.formProps?.readonly === true}
43+
id={name}
44+
{...inputProps}
45+
disabled={formProps?.readonly}
46+
placeholder={placeholder}
4447
/>
4548
</div>
4649
)

library/src/components/form/elements/SelectMultiFormField.tsx

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,61 @@
1-
import React, {useEffect} from "react"
2-
import {FieldValues, Path} from "react-hook-form"
3-
import {FormField} from "../DynamicForm";
4-
import {Label, Select} from "../../inputs";
1+
import { useEffect, useRef } from "react"
2+
import type { FieldValues } from "react-hook-form"
3+
import type { FormField } from "../DynamicForm"
4+
import { Label, Select } from "../../inputs"
55

6-
export interface SelectMultiFormField<T extends FieldValues, A extends string | number>
7-
extends FormField<T> {
6+
export interface SelectMultiFormField<
7+
T extends FieldValues,
8+
A extends string | number,
9+
> extends FormField<T> {
810
options: Array<{ label: string; value: A }>
911
onChange?: (values: Array<string>) => void
12+
placeholder?: string
1013
}
1114

12-
export function SelectMultiFormField<T extends FieldValues, A extends string | number>(
13-
props: SelectMultiFormField<T, A>,
14-
) {
15-
const fieldValue = props.formProps?.watch(props.objKey as Path<T>)
15+
export function SelectMultiFormField<
16+
T extends FieldValues,
17+
A extends string | number,
18+
>({
19+
name,
20+
onChange,
21+
formProps,
22+
required,
23+
description,
24+
title,
25+
options,
26+
placeholder,
27+
}: SelectMultiFormField<T, A>) {
28+
const fieldValue = formProps.watch(name)
29+
const onChangeCB = useRef(onChange)
30+
if (onChangeCB.current !== onChange) {
31+
onChangeCB.current = onChange
32+
}
1633

1734
useEffect(() => {
18-
console.info("FieldChange", props.objKey, fieldValue, props.onChange)
19-
if (props.onChange) {
20-
console.info(
21-
"FieldChange EXECUTING",
22-
props.objKey,
23-
fieldValue,
24-
props.onChange,
25-
)
26-
// @ts-ignore
27-
props.onChange(fieldValue)
28-
}
35+
onChangeCB.current?.(fieldValue)
2936
}, [fieldValue])
3037

31-
const inputProps = props.formProps?.register(props.objKey)
38+
const inputProps = formProps.register(name)
3239

3340
return (
34-
<div className="flex flex-1 flex-col">
35-
<Label htmlFor={inputProps?.name} required={props.required}>
36-
{props.title}
41+
<div className="flex flex-1 flex-col min-w-max">
42+
<Label htmlFor={inputProps?.name} required={required}>
43+
{title}
3744
</Label>
45+
{description && (
46+
<p className="mt-0 pb-2">
47+
<small>{description}</small>
48+
</p>
49+
)}
3850
<Select<T, A, true>
3951
isMulti
40-
id={inputProps?.name}
41-
name={inputProps?.name as Path<T>}
42-
control={props.formProps!.control}
43-
options={props.options}
44-
required
45-
disabled={props.formProps?.readonly === true}
52+
id={name}
53+
name={name}
54+
control={formProps.control}
55+
options={options}
56+
required={required}
57+
disabled={formProps.readonly}
58+
placeholder={placeholder}
4659
/>
4760
</div>
4861
)

0 commit comments

Comments
 (0)