diff options
Diffstat (limited to 'packages/web-util/src/forms/DefaultForm.tsx')
-rw-r--r-- | packages/web-util/src/forms/DefaultForm.tsx | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/packages/web-util/src/forms/DefaultForm.tsx b/packages/web-util/src/forms/DefaultForm.tsx new file mode 100644 index 000000000..1c635e089 --- /dev/null +++ b/packages/web-util/src/forms/DefaultForm.tsx @@ -0,0 +1,83 @@ +import { Fragment, VNode, h } from "preact"; +import { FormProvider, FormProviderProps, FormState } from "./FormProvider.js"; +import { RenderAllFieldsByUiConfig, UIFormField } from "./forms.js"; +import { TranslatedString } from "@gnu-taler/taler-util"; + +/** + * Flexible form uses a DoubleColumForm for design + * and may have a dynamic properties defined by + * behavior function. + */ +export interface FlexibleForm<T extends object> { + design: DoubleColumnForm; + behavior?: (form: Partial<T>) => FormState<T>; +} + +/** + * Double column form + * + * Form with sections, every sections have a title and may + * have a description. + * Every sections contain a set of fields. + */ +export type DoubleColumnForm = Array<DoubleColumnFormSection | undefined>; + +export type DoubleColumnFormSection = { + title: TranslatedString; + description?: TranslatedString; + fields: UIFormField[]; +}; + +/** + * Form Provider implementation that use FlexibleForm + * to defined behavior and fields. + */ +export function DefaultForm<T extends object>({ + initial, + onUpdate, + form, + onSubmit, + children, + readOnly, +}: Omit<FormProviderProps<T>, "computeFormState"> & { form: FlexibleForm<T> }): VNode { + return ( + <FormProvider + initial={initial} + onUpdate={onUpdate} + onSubmit={onSubmit} + readOnly={readOnly} + computeFormState={form.behavior} + > + <div class="space-y-10 divide-y -mt-5 divide-gray-900/10"> + {form.design.map((section, i) => { + if (!section) return <Fragment />; + return ( + <div key={i} class="grid grid-cols-1 gap-x-8 gap-y-8 pt-5 md:grid-cols-3"> + <div class="px-4 sm:px-0"> + <h2 class="text-base font-semibold leading-7 text-gray-900"> + {section.title} + </h2> + {section.description && ( + <p class="mt-1 text-sm leading-6 text-gray-600"> + {section.description} + </p> + )} + </div> + <div class="bg-white shadow-sm ring-1 ring-gray-900/5 rounded-md md:col-span-2"> + <div class="p-3"> + <div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"> + <RenderAllFieldsByUiConfig + key={i} + fields={section.fields} + /> + </div> + </div> + </div> + </div> + ); + })} + </div> + {children} + </FormProvider> + ); +} |