import { TranslatedString } from "@gnu-taler/taler-util"; import { InputText } from "./InputText.js"; import { InputDate } from "./InputDate.js"; import { InputInteger } from "./InputInteger.js"; import { h as create, Fragment, VNode } from "preact"; import { InputChoiceStacked } from "./InputChoice.js"; import { InputArray } from "./InputArray.js"; import { InputSelectMultiple } from "./InputSelectMultiple.js"; import { InputTextArea } from "./InputTextArea.js"; import { InputFile } from "./InputFile.js"; export type DoubleColumnForm = DoubleColumnFormSection[]; type DoubleColumnFormSection = { title: TranslatedString; description?: TranslatedString; fields: UIFormField[]; }; /** * Constrain the type with the ui props */ type FieldType = { separator: {}; array: Parameters[0]; file: Parameters[0]; selectMultiple: Parameters[0]; text: Parameters[0]; textArea: Parameters[0]; choiceStacked: Parameters[0]; date: Parameters[0]; integer: Parameters[0]; }; /** * List all the form fields so typescript can type-check the form instance */ export type UIFormField = | { type: "separator"; props: FieldType["separator"] } | { type: "array"; props: FieldType["array"] } | { type: "file"; props: FieldType["file"] } | { type: "selectMultiple"; props: FieldType["selectMultiple"] } | { type: "text"; props: FieldType["text"] } | { type: "textArea"; props: FieldType["textArea"] } | { type: "choiceStacked"; props: FieldType["choiceStacked"] } | { type: "integer"; props: FieldType["integer"] } | { type: "date"; props: FieldType["date"] }; type FieldComponentFunction = ( props: FieldType[key], ) => VNode; type UIFormFieldMap = { [key in keyof FieldType]: FieldComponentFunction; }; function Separator(): VNode { return create("div", {}); } /** * Maps input type with component implementation */ const UIFormConfiguration: UIFormFieldMap = { separator: Separator, array: InputArray, text: InputText, file: InputFile, textArea: InputTextArea, date: InputDate, choiceStacked: InputChoiceStacked, integer: InputInteger, selectMultiple: InputSelectMultiple, }; export function RenderAllFieldsByUiConfig({ fields, }: { fields: UIFormField[]; }): VNode { return create( Fragment, {}, fields.map((field, i) => { const Component = UIFormConfiguration[ field.type ] as FieldComponentFunction; const c = structuredClone(field.props); c.key = i; return Component(c); }), ); }