diff --git a/apps/backend/schema.gql b/apps/backend/schema.gql index 0694809c4..81b005c66 100644 --- a/apps/backend/schema.gql +++ b/apps/backend/schema.gql @@ -227,7 +227,6 @@ type Mutation { admin__core_languages__delete(code: String!): String! admin__core_languages__download(code: String!, plugins: [String!]!): String! admin__core_languages__edit(allow_in_input: Boolean!, default: Boolean!, enabled: Boolean!, id: Int!, locale: String!, name: String!, time_24: Boolean!, timezone: String!): ShowCoreLanguages! - admin__core_languages__update(code: String!, file: Upload!): String! admin__core_main_settings__edit(site_copyright: [TextLanguageInput!]!, site_description: [TextLanguageInput!]!, site_name: String!, site_short_name: String!): EditAdminSettingsObj! admin__core_manifest_metadata__edit(background_color: String!, display: String!, start_url: String!, theme_color: String!): ShowAdminManifestMetadataObj! admin__core_members__create(email: String!, name: String!, password: String!): SignUpCoreSessionsObj! diff --git a/apps/docs/assets/ui/components/tags-input.png b/apps/docs/assets/ui/components/tag-input.png similarity index 100% rename from apps/docs/assets/ui/components/tags-input.png rename to apps/docs/assets/ui/components/tag-input.png diff --git a/apps/docs/content/docs/ui/forms/auto-form.mdx b/apps/docs/content/docs/ui/forms/auto-form.mdx index 243a035fa..5246af1ed 100644 --- a/apps/docs/content/docs/ui/forms/auto-form.mdx +++ b/apps/docs/content/docs/ui/forms/auto-form.mdx @@ -3,8 +3,6 @@ title: Auto Form description: Automatically generate form fields based on a schema. --- -Component created based on [Auto Form by vantezzen](https://github.com/vantezzen/auto-form). - ## Support Fileds - [Color Picker](/docs/ui/forms/color-picker) @@ -17,7 +15,7 @@ Component created based on [Auto Form by vantezzen](https://github.com/vantezzen - [Switch](/docs/ui/forms/switch) - [Text Language Input](/docs/ui/forms/text-language-input) - [Icon Picker](/docs/ui/forms/icon-picker) -- [Tags Input](/docs/ui/forms/tags-input) +- [Tag Input](/docs/ui/forms/tag-input) - [Combobox](/docs/ui/forms/combobox) - [Date Picker](/docs/ui/forms/date-picker) @@ -56,57 +54,80 @@ const formSchema = z.object({ ```tsx ``` -## Zod Configuration - -### Validators - -Our component is smart and well integrated with Zod, so you can use all the validators that Zod provides. For exampele if you use `zod.string().min(8)`, the input will automatically have a minlength="8" attribute. +## Component Props -Validation methods not supported by HTML will automatically be checked when the form is submitted. +Each field has a set of props with `Props` surfix that can be passed to the component. For example, for the `AutoFormInput` component, you can pass the `AutoFormInputProps` props using the `componentProps` prop. -### Descriptions - -You can add a description to your schema fields by using the `description` method. +```tsx +import { + AutoFormInput, + AutoFormInputProps, +} from 'vitnode-frontend/components/auto-form/fields/input'; -```ts -const formSchema = z.object({ - username: z.string().describe('Your username'), -}); +; ``` -or using the `description` method in the `fieldConfig` object. + + Do not use function for component argument like this: ```tsx , // [!code highlight] }, - }} + ]} /> ``` -You can also use the `description` as function to get the current value of the field. +This will cause the component to re-render on every change. + + + +## Zod Configuration + +### Validators + +Our component is smart and well integrated with Zod, so you can use all the validators that Zod provides. For exampele if you use `zod.string().min(8)`, the input will automatically have a minlength="8" attribute. + +Validation methods not supported by HTML will automatically be checked when the form is submitted. + +### Descriptions + +You can add a description to your field by passing the `description` prop. ```tsx `The current value is ${value}`, + fields={[ + { + id: 'username', + component: AutoFormInput, + description: 'Test description', // [!code highlight] }, - }} + ]} /> ``` @@ -137,12 +158,13 @@ You can set a label for a field by using the `label` method. ```tsx ``` @@ -210,31 +232,31 @@ const formSchema = z.object({ /> ``` -### Render Parent - -You can render the parent object by using the `renderParent` prop. - -Avaliable props: +### Child Component -- `children`: The children of the parent object. -- `field`: The field object `ControllerRenderProps` from `react-hook-form`. +If you want to render something below the field, you can use the `childComponent` prop. ```tsx , - renderParent: ({ children, field }: FieldRenderParentProps) => ( -
- Something - {children} // Here is the input -
- ), + fields={[ + { + id: 'name', + label: t('sign_up.form.name.label'), + description: t('sign_up.form.name.desc'), + component: AutoFormInput, + childComponent: ({ field }) => { + const value: string = field.value ?? ''; + if (!value.length) return null; + + return ( + + {value} + + ); + }, }, - }} + ]} /> ``` @@ -245,11 +267,12 @@ You can use the `onSubmit` prop to get the form data. ```tsx { console.log(data); }} @@ -261,15 +284,17 @@ You can get access to the `form` from `react-hook-form` by using the `form` prop ```tsx { console.log(data); - form.setError("username", { type: "manual", message: "This is an error" }); + form.setError('username', { type: 'manual', message: 'This is an error' }); }} +/> ``` You can also move `onSubmit` to a separate function. @@ -315,11 +340,12 @@ Component has a submit button by default with the text `Save` include translatio ```tsx ( - - - - - {t('no_results')} - - {values.map(([value, labelFromProps]) => { - const label = labels?.[value] ?? labelFromProps; - const currentArrayValues = Array.isArray(field.value) - ? field.value - : field.value - ? [field.value] - : []; + {ChildComponent && } + + + + + + {t('no_results')} + + {values.map(([valueItem, labelFromProps]) => { + const label = + componentProps?.labels?.[valueItem] ?? labelFromProps; + const currentArrayValues = Array.isArray(value) + ? value + : value + ? [value] + : []; + + return ( + { + if (componentProps?.multiple) { + field.onChange( + currentArrayValues.includes(valueItem) + ? currentArrayValues.filter( + el => el !== valueItem, + ) + : [...currentArrayValues, valueItem], + ); - return ( - { - if (multiple) { - field.onChange( - currentArrayValues.includes(value) - ? currentArrayValues.filter(el => el !== value) - : [...currentArrayValues, value], - ); + return; + } - return; - } + field.onChange(valueItem); + setOpen(false); + }} + value={labelFromProps} + > + + {label} + + ); + })} + + + + + - field.onChange(value); - setOpen(false); - }} - value={labelFromProps} - > - - {label} - - ); - })} - - - - - - - {fieldConfigItem.description && theme === 'vertical' && ( - + {description && theme === 'vertical' && ( + )} ); -}; +} diff --git a/packages/frontend/src/components/form/fields/common/children.tsx b/packages/frontend/src/components/form/fields/common/children.tsx deleted file mode 100644 index cb3a4f315..000000000 --- a/packages/frontend/src/components/form/fields/common/children.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export const DefaultParent = ({ children }: { children: React.ReactNode }) => { - return <>{children}; -}; diff --git a/packages/frontend/src/components/form/fields/common/input-wrapper.tsx b/packages/frontend/src/components/form/fields/common/input-wrapper.tsx new file mode 100644 index 000000000..828df2b80 --- /dev/null +++ b/packages/frontend/src/components/form/fields/common/input-wrapper.tsx @@ -0,0 +1,15 @@ +export const AutoFormInputWrapper = ({ + withChildren, + className, + children, +}: { + children: React.ReactNode; + className?: string; + withChildren: boolean; +}) => { + if (className || withChildren) { + return
{children}
; + } + + return <>{children}; +}; diff --git a/packages/frontend/src/components/form/fields/common/label.tsx b/packages/frontend/src/components/form/fields/common/label.tsx index e6723451c..8e79e6977 100644 --- a/packages/frontend/src/components/form/fields/common/label.tsx +++ b/packages/frontend/src/components/form/fields/common/label.tsx @@ -1,8 +1,6 @@ import { FormLabel } from '@/components/ui/form'; import { cn } from '@/helpers/classnames'; -import { AutoFormInputComponentProps } from '../../type'; - export const AutoFormLabel = ({ label, isRequired, @@ -14,7 +12,7 @@ export const AutoFormLabel = ({ description: React.ReactNode | undefined; isRequired: boolean; label: string; - theme: AutoFormInputComponentProps['autoFormProps']['theme']; + theme: 'horizontal' | 'vertical'; }) => { return ( { return ( , + 'onChange' | 'value' +>; + +export function AutoFormDatePicker({ + field, + label, + description, + isRequired, + theme, + isDisabled, + componentProps, + className, + childComponent: ChildComponent, +}: { + componentProps?: AutoFormDatePickerProps; +} & AutoFormItemProps) { + return ( + + {label && ( + + )} + + + + + + {ChildComponent && } + + + {description && theme === 'vertical' && ( + + )} + + + ); +} diff --git a/packages/frontend/src/components/form/fields/date.tsx b/packages/frontend/src/components/form/fields/date.tsx deleted file mode 100644 index dc16ae1d8..000000000 --- a/packages/frontend/src/components/form/fields/date.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { DatePicker } from '@/components/ui/date-picker'; -import { FormControl, FormMessage } from '@/components/ui/form'; - -import { AutoFormInputComponentProps } from '../type'; -import { DefaultParent } from './common/children'; -import { AutoFormLabel } from './common/label'; -import { AutoFormTooltip } from './common/tooltip'; -import { AutoFormWrapper } from './common/wrapper'; - -export const AutoFormDate = ({ - autoFormProps: { isRequired, fieldConfigItem, field, theme, isDisabled }, - ...props -}: AutoFormInputComponentProps & - Omit, 'onChange' | 'value'>) => { - const ParentWrapper = fieldConfigItem.renderParent ?? DefaultParent; - - return ( - - {fieldConfigItem.label && ( - - )} - - - - - - {fieldConfigItem.description && theme === 'vertical' && ( - - )} - - - ); -}; diff --git a/packages/frontend/src/components/form/fields/file-input.tsx b/packages/frontend/src/components/form/fields/file-input.tsx new file mode 100644 index 000000000..4b365366c --- /dev/null +++ b/packages/frontend/src/components/form/fields/file-input.tsx @@ -0,0 +1,64 @@ +'use client'; + +import { FileInput } from '@/components/ui/file-input'; +import { FormControl, FormMessage } from '@/components/ui/form'; +import { FieldValues } from 'react-hook-form'; + +import { AutoFormItemProps } from '../auto-form'; +import { AutoFormInputWrapper } from './common/input-wrapper'; +import { AutoFormLabel } from './common/label'; +import { AutoFormTooltip } from './common/tooltip'; +import { AutoFormWrapper } from './common/wrapper'; + +export type AutoFormFileInputProps = Omit< + React.ComponentProps, + 'onChange' | 'value' +>; + +export function AutoFormFileInput({ + field, + label, + description, + isRequired, + theme, + isDisabled, + componentProps, + className, + childComponent: ChildComponent, +}: { + componentProps?: AutoFormFileInputProps; +} & AutoFormItemProps) { + return ( + + {label && ( + + )} + + + + + + {ChildComponent && } + + + {description && theme === 'vertical' && ( + + )} + + + ); +} diff --git a/packages/frontend/src/components/form/fields/file.tsx b/packages/frontend/src/components/form/fields/file.tsx deleted file mode 100644 index b6233cc4d..000000000 --- a/packages/frontend/src/components/form/fields/file.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { FileInput } from '@/components/ui/file-input'; -import { FormControl, FormMessage } from '@/components/ui/form'; - -import { AutoFormInputComponentProps } from '../type'; -import { DefaultParent } from './common/children'; -import { AutoFormLabel } from './common/label'; -import { AutoFormTooltip } from './common/tooltip'; -import { AutoFormWrapper } from './common/wrapper'; - -export const AutoFormFile = ({ - autoFormProps: { isRequired, fieldConfigItem, field, theme, isDisabled }, - ...props -}: AutoFormInputComponentProps & - Omit, 'onChange' | 'value'>) => { - const ParentWrapper = fieldConfigItem.renderParent ?? DefaultParent; - - return ( - - {fieldConfigItem.label && ( - - )} - - - - - - {fieldConfigItem.description && theme === 'vertical' && ( - - )} - - - ); -}; diff --git a/packages/frontend/src/components/form/fields/icon-picker.tsx b/packages/frontend/src/components/form/fields/icon-picker.tsx new file mode 100644 index 000000000..9e84445ea --- /dev/null +++ b/packages/frontend/src/components/form/fields/icon-picker.tsx @@ -0,0 +1,69 @@ +'use client'; + +import { IconPicker } from '@/components/icon/picker/icon-picker'; +import { FormControl, FormMessage } from '@/components/ui/form'; +import { FieldValues } from 'react-hook-form'; + +import { AutoFormItemProps } from '../auto-form'; +import { AutoFormInputWrapper } from './common/input-wrapper'; +import { AutoFormLabel } from './common/label'; +import { AutoFormTooltip } from './common/tooltip'; +import { AutoFormWrapper } from './common/wrapper'; + +export type AutoFormIconPickerProps = Omit< + React.ComponentProps, + 'onChange' | 'value' +>; + +export function AutoFormIconPicker({ + field, + zodInputProps, + label, + description, + isRequired, + theme, + isDisabled, + componentProps, + className, + childComponent: ChildComponent, +}: { + componentProps?: AutoFormIconPickerProps; +} & AutoFormItemProps) { + const value = field.value || ''; + + return ( + + {label && ( + + )} + + + + void} + value={value} + /> + + {ChildComponent && } + + + {description && theme === 'vertical' && ( + + )} + + + ); +} diff --git a/packages/frontend/src/components/form/fields/icon.tsx b/packages/frontend/src/components/form/fields/icon.tsx deleted file mode 100644 index dd8020e57..000000000 --- a/packages/frontend/src/components/form/fields/icon.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { IconPicker } from '@/components/icon/picker/icon-picker'; -import { FormControl, FormMessage } from '@/components/ui/form'; - -import { AutoFormInputComponentProps } from '../type'; -import { DefaultParent } from './common/children'; -import { AutoFormLabel } from './common/label'; -import { AutoFormTooltip } from './common/tooltip'; -import { AutoFormWrapper } from './common/wrapper'; - -export const AutoFormIcon = ({ - autoFormProps: { isRequired, fieldConfigItem, field, theme, isDisabled }, - ...props -}: AutoFormInputComponentProps & - Omit, 'onChange' | 'value'>) => { - const value = field.value || ''; - const ParentWrapper = fieldConfigItem.renderParent ?? DefaultParent; - - return ( - - {fieldConfigItem.label && ( - - )} - - - - - - {fieldConfigItem.description && theme === 'vertical' && ( - - )} - - - ); -}; diff --git a/packages/frontend/src/components/form/fields/input.tsx b/packages/frontend/src/components/form/fields/input.tsx index 19bee81b0..1fc231ef9 100644 --- a/packages/frontend/src/components/form/fields/input.tsx +++ b/packages/frontend/src/components/form/fields/input.tsx @@ -1,44 +1,64 @@ +'use client'; + import { FormControl, FormMessage } from '@/components/ui/form'; import { Input } from '@/components/ui/input'; +import { FieldValues } from 'react-hook-form'; -import { AutoFormInputComponentProps } from '../type'; -import { DefaultParent } from './common/children'; +import { AutoFormItemProps } from '../auto-form'; +import { AutoFormInputWrapper } from './common/input-wrapper'; import { AutoFormLabel } from './common/label'; import { AutoFormTooltip } from './common/tooltip'; import { AutoFormWrapper } from './common/wrapper'; -export const AutoFormInput = ({ - autoFormProps: { isRequired, fieldConfigItem, field, theme, isDisabled }, - ...props -}: AutoFormInputComponentProps & - React.InputHTMLAttributes) => { - const value = field.value || ''; - const ParentWrapper = fieldConfigItem.renderParent ?? DefaultParent; +export type AutoFormInputProps = Omit< + React.InputHTMLAttributes, + 'onChange' | 'value' +>; +export function AutoFormInput({ + field, + zodInputProps, + label, + description, + isRequired, + theme, + isDisabled, + componentProps, + className, + childComponent: ChildComponent, +}: { + componentProps?: AutoFormInputProps; +} & AutoFormItemProps) { return ( - {fieldConfigItem.label && ( + {label && ( )} - + + - - {fieldConfigItem.description && theme === 'vertical' && ( - + {ChildComponent && } + + + {description && theme === 'vertical' && ( + )} ); -}; +} diff --git a/packages/frontend/src/components/form/fields/radio-group.tsx b/packages/frontend/src/components/form/fields/radio-group.tsx index 5a5c5edbd..e4cfb5967 100644 --- a/packages/frontend/src/components/form/fields/radio-group.tsx +++ b/packages/frontend/src/components/form/fields/radio-group.tsx @@ -1,3 +1,6 @@ +'use client'; + +import { getBaseSchema } from '@/components/form/utils'; import { FormControl, FormItem, @@ -5,27 +8,17 @@ import { FormMessage, } from '@/components/ui/form'; import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; +import React from 'react'; +import { FieldValues } from 'react-hook-form'; import * as z from 'zod'; -import { AutoFormInputComponentProps } from '../type'; -import { getBaseSchema } from '../utils'; -import { DefaultParent } from './common/children'; +import { AutoFormItemProps } from '../auto-form'; +import { AutoFormInputWrapper } from './common/input-wrapper'; import { AutoFormLabel } from './common/label'; import { AutoFormTooltip } from './common/tooltip'; import { AutoFormWrapper } from './common/wrapper'; -export const AutoFormRadioGroup = ({ - autoFormProps: { - isRequired, - fieldConfigItem, - zodItem, - field, - theme, - isDisabled, - }, - labels, - ...props -}: { +export type AutoFormRadioGroupProps = { labels?: Record< string, { @@ -33,11 +26,25 @@ export const AutoFormRadioGroup = ({ title: string; } >; -} & AutoFormInputComponentProps & - React.ComponentProps) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const baseValues = (getBaseSchema(zodItem) as unknown as z.ZodEnum)._def - .values; +} & Omit, 'role' | 'variant'>; + +export function AutoFormRadioGroup({ + field, + label, + description, + isRequired, + theme, + isDisabled, + shape, + componentProps, + className, + childComponent: ChildComponent, +}: { + componentProps?: AutoFormRadioGroupProps; +} & AutoFormItemProps) { + const baseValues = ( + getBaseSchema(shape, true) as unknown as z.ZodEnum<[string, ...string[]]> + )._def.values; let values: [string, string][] = []; if (!Array.isArray(baseValues)) { @@ -46,30 +53,34 @@ export const AutoFormRadioGroup = ({ values = baseValues.map(value => [value, value]); } - const ParentWrapper = fieldConfigItem.renderParent ?? DefaultParent; - return ( - {fieldConfigItem.label && ( + {label && ( )} - + + {/* eslint-disable-next-line @typescript-eslint/no-explicit-any */} {values.map((value: any) => { - const label = labels?.[value[0]]?.title ?? value[1]; - const description = labels?.[value[0]]?.description; + const label = + componentProps?.labels?.[value[0]]?.title ?? value[1]; + const description = + componentProps?.labels?.[value[0]]?.description; return ( - - {fieldConfigItem.description && theme === 'vertical' && ( - + {ChildComponent && } + + + {description && theme === 'vertical' && ( + )} ); -}; +} diff --git a/packages/frontend/src/components/form/fields/select.tsx b/packages/frontend/src/components/form/fields/select.tsx index 686a35f8d..efde663d6 100644 --- a/packages/frontend/src/components/form/fields/select.tsx +++ b/packages/frontend/src/components/form/fields/select.tsx @@ -1,3 +1,6 @@ +'use client'; + +import { getBaseSchema } from '@/components/form/utils'; import { FormControl, FormMessage } from '@/components/ui/form'; import { Select, @@ -7,37 +10,39 @@ import { SelectValue, } from '@/components/ui/select'; import { useTranslations } from 'next-intl'; +import React from 'react'; +import { FieldValues } from 'react-hook-form'; import * as z from 'zod'; -import { AutoFormInputComponentProps } from '../type'; -import { getBaseSchema } from '../utils'; -import { DefaultParent } from './common/children'; +import { AutoFormItemProps } from '../auto-form'; +import { AutoFormInputWrapper } from './common/input-wrapper'; import { AutoFormLabel } from './common/label'; import { AutoFormTooltip } from './common/tooltip'; import { AutoFormWrapper } from './common/wrapper'; -export const AutoFormSelect = ({ - autoFormProps: { - isRequired, - fieldConfigItem, - zodItem, - field, - theme, - isDisabled, - }, - labels, - placeholder, - ...props -}: { +export type AutoFormSelectProps = { labels?: Record; placeholder?: string; -} & AutoFormInputComponentProps & - Omit, 'onValueChange'>) => { +} & Omit, 'onValueChange' | 'value'>; + +export function AutoFormSelect({ + field, + label, + description, + isRequired, + theme, + isDisabled, + shape, + componentProps, + className, + childComponent: ChildComponent, +}: { + componentProps?: AutoFormSelectProps; +} & AutoFormItemProps) { const t = useTranslations('core'); - const ParentWrapper = fieldConfigItem.renderParent ?? DefaultParent; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const baseValues = (getBaseSchema(zodItem) as unknown as z.ZodEnum)._def - .values; + const baseValues = ( + getBaseSchema(shape, true) as unknown as z.ZodEnum<[string, ...string[]]> + )._def.values; let values: [string, string][] = []; if (!Array.isArray(baseValues)) { @@ -51,7 +56,7 @@ export const AutoFormSelect = ({ const item = current?.[1]; if (current) { - return labels?.[current[0]] ?? item; + return componentProps?.labels?.[current[0]] ?? item; } return item ?? t('select_option'); @@ -59,30 +64,33 @@ export const AutoFormSelect = ({ return ( - {fieldConfigItem.label && ( + {label && ( )} - + + - - {fieldConfigItem.description && theme === 'vertical' && ( - + {ChildComponent && } + + + {description && theme === 'vertical' && ( + )} ); -}; +} diff --git a/packages/frontend/src/components/form/fields/switch.tsx b/packages/frontend/src/components/form/fields/switch.tsx index c99d13d1c..34bd20868 100644 --- a/packages/frontend/src/components/form/fields/switch.tsx +++ b/packages/frontend/src/components/form/fields/switch.tsx @@ -1,18 +1,35 @@ +'use client'; + import { FormControl, FormMessage } from '@/components/ui/form'; import { Switch } from '@/components/ui/switch'; import { cn } from '@/helpers/classnames'; +import { FieldValues } from 'react-hook-form'; -import { AutoFormInputComponentProps } from '../type'; -import { DefaultParent } from './common/children'; +import { AutoFormItemProps } from '../auto-form'; +import { AutoFormInputWrapper } from './common/input-wrapper'; import { AutoFormLabel } from './common/label'; import { AutoFormTooltip } from './common/tooltip'; import { AutoFormWrapper } from './common/wrapper'; -export const AutoFormSwitch = ({ - autoFormProps: { isRequired, fieldConfigItem, field, theme, isDisabled }, - ...props -}: AutoFormInputComponentProps & React.ComponentProps) => { - const ParentWrapper = fieldConfigItem.renderParent ?? DefaultParent; +export type AutoFormSwitchProps = Omit< + React.ComponentProps, + 'checked' +>; + +export function AutoFormSwitch({ + field, + label, + description, + isRequired, + theme, + isDisabled, + componentProps, + className, + childComponent: ChildComponent, +}: { + componentProps?: AutoFormSwitchProps; +} & AutoFormItemProps) { + const value: boolean = field.value || false; return (
- {fieldConfigItem.label && ( + {label && ( )} - {fieldConfigItem.description && theme === 'vertical' && ( - + {description && theme === 'vertical' && ( + )}
- + + { field.onChange(e); - props.onCheckedChange?.(e); + componentProps?.onCheckedChange?.(e); }} - {...props} - disabled={isDisabled || props.disabled} + {...componentProps} + disabled={isDisabled || componentProps?.disabled} /> - + {ChildComponent && } +
); -}; +} diff --git a/packages/frontend/src/components/form/fields/tags-input.tsx b/packages/frontend/src/components/form/fields/tags-input.tsx new file mode 100644 index 000000000..b4546e5df --- /dev/null +++ b/packages/frontend/src/components/form/fields/tags-input.tsx @@ -0,0 +1,62 @@ +'use client'; + +import { FormControl, FormMessage } from '@/components/ui/form'; +import { TagInput } from '@/components/ui/tag-input'; +import { FieldValues } from 'react-hook-form'; + +import { AutoFormItemProps } from '../auto-form'; +import { AutoFormInputWrapper } from './common/input-wrapper'; +import { AutoFormLabel } from './common/label'; +import { AutoFormTooltip } from './common/tooltip'; +import { AutoFormWrapper } from './common/wrapper'; + +export type AutoFormTagInputProps = Omit< + React.ComponentProps, + 'onChange' | 'value' +>; + +export function AutoFormTagInput({ + field, + label, + description, + isRequired, + theme, + isDisabled, + componentProps, + className, + childComponent: ChildComponent, +}: { + componentProps?: AutoFormTagInputProps; +} & AutoFormItemProps) { + return ( + + {label && ( + + )} + + + + + + {ChildComponent && } + + + {description && theme === 'vertical' && ( + + )} + + + ); +} diff --git a/packages/frontend/src/components/form/fields/tags.tsx b/packages/frontend/src/components/form/fields/tags.tsx deleted file mode 100644 index dc1e1c601..000000000 --- a/packages/frontend/src/components/form/fields/tags.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { FormControl, FormMessage } from '@/components/ui/form'; -import { TagsInput } from '@/components/ui/tags-input'; - -import { AutoFormInputComponentProps } from '../type'; -import { DefaultParent } from './common/children'; -import { AutoFormLabel } from './common/label'; -import { AutoFormTooltip } from './common/tooltip'; -import { AutoFormWrapper } from './common/wrapper'; - -export const AutoFormTags = ({ - autoFormProps: { isRequired, fieldConfigItem, field, theme, isDisabled }, - ...props -}: AutoFormInputComponentProps & - Omit, 'onChange'>) => { - const value = field.value || ''; - const ParentWrapper = fieldConfigItem.renderParent ?? DefaultParent; - - return ( - - {fieldConfigItem.label && ( - - )} - - - - - - {fieldConfigItem.description && theme === 'vertical' && ( - - )} - - - ); -}; diff --git a/packages/frontend/src/components/form/fields/text-language-input.tsx b/packages/frontend/src/components/form/fields/text-language-input.tsx index 22a1905fe..83e396044 100644 --- a/packages/frontend/src/components/form/fields/text-language-input.tsx +++ b/packages/frontend/src/components/form/fields/text-language-input.tsx @@ -1,45 +1,67 @@ +'use client'; + import { FormControl, FormMessage } from '@/components/ui/form'; import { TextLanguageInput } from '@/components/ui/text-language-input'; +import { TextLanguage } from '@/graphql/types'; +import { FieldValues } from 'react-hook-form'; -import { AutoFormInputComponentProps } from '../type'; -import { DefaultParent } from './common/children'; +import { AutoFormItemProps } from '../auto-form'; +import { AutoFormInputWrapper } from './common/input-wrapper'; import { AutoFormLabel } from './common/label'; import { AutoFormTooltip } from './common/tooltip'; import { AutoFormWrapper } from './common/wrapper'; -export const AutoFormTextLanguageInput = ({ - autoFormProps: { isRequired, fieldConfigItem, field, theme, isDisabled }, - ...props -}: AutoFormInputComponentProps & - Omit< - React.ComponentProps, - 'onChange' | 'value' - >) => { - const ParentWrapper = fieldConfigItem.renderParent ?? DefaultParent; +export type AutoFormTextLanguageInputProps = Omit< + React.ComponentProps, + 'onChange' | 'value' +>; +export function AutoFormTextLanguageInput({ + field, + zodInputProps, + label, + description, + isRequired, + theme, + isDisabled, + componentProps, + className, + childComponent: ChildComponent, +}: { + componentProps?: AutoFormTextLanguageInputProps; +} & AutoFormItemProps) { return ( - {fieldConfigItem.label && ( + {label && ( )} - + + void} + value={field.value as TextLanguage[]} /> - - {fieldConfigItem.description && theme === 'vertical' && ( - + {ChildComponent && } + + + {description && theme === 'vertical' && ( + )} ); -}; +} diff --git a/packages/frontend/src/components/form/fields/textarea.tsx b/packages/frontend/src/components/form/fields/textarea.tsx index 908f20b55..a2b9d4ccb 100644 --- a/packages/frontend/src/components/form/fields/textarea.tsx +++ b/packages/frontend/src/components/form/fields/textarea.tsx @@ -1,45 +1,67 @@ +'use client'; + import { FormControl, FormMessage } from '@/components/ui/form'; import { Textarea } from '@/components/ui/textarea'; +import { FieldValues } from 'react-hook-form'; -import { AutoFormInputComponentProps } from '../type'; -import { DefaultParent } from './common/children'; +import { AutoFormItemProps } from '../auto-form'; +import { AutoFormInputWrapper } from './common/input-wrapper'; import { AutoFormLabel } from './common/label'; import { AutoFormTooltip } from './common/tooltip'; import { AutoFormWrapper } from './common/wrapper'; -export const AutoFormTextArea = ({ - autoFormProps: { isRequired, fieldConfigItem, field, theme, isDisabled }, - ...props -}: AutoFormInputComponentProps & - React.InputHTMLAttributes) => { - const value = field.value || ''; +export type AutoFormTextAreaProps = Omit< + React.InputHTMLAttributes, + 'onChange' | 'value' +>; - const ParentWrapper = fieldConfigItem.renderParent ?? DefaultParent; +export function AutoTextArea({ + field, + zodInputProps, + label, + description, + isRequired, + theme, + isDisabled, + componentProps, + className, + childComponent: ChildComponent, +}: { + componentProps?: AutoFormTextAreaProps; +} & AutoFormItemProps) { + const value = field.value || ''; return ( - {fieldConfigItem.label && ( + {label && ( )} - + +