From fdbe623e1060efc4b074d213a96e8f5a2ab7498b Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 20 Sep 2023 15:16:28 -0300 Subject: more ui stuff, moved forms to util --- packages/web-util/src/forms/forms.ts | 135 +++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 packages/web-util/src/forms/forms.ts (limited to 'packages/web-util/src/forms/forms.ts') diff --git a/packages/web-util/src/forms/forms.ts b/packages/web-util/src/forms/forms.ts new file mode 100644 index 000000000..2c90a69ed --- /dev/null +++ b/packages/web-util/src/forms/forms.ts @@ -0,0 +1,135 @@ +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 "./InputChoiceStacked.js"; +import { InputArray } from "./InputArray.js"; +import { InputSelectMultiple } from "./InputSelectMultiple.js"; +import { InputTextArea } from "./InputTextArea.js"; +import { InputFile } from "./InputFile.js"; +import { Caption } from "./Caption.js"; +import { Group } from "./Group.js"; +import { InputSelectOne } from "./InputSelectOne.js"; +import { FormProvider } from "./FormProvider.js"; +import { InputLine } from "./InputLine.js"; +import { InputAmount } from "./InputAmount.js"; +import { InputChoiceHorizontal } from "./InputChoiceHorizontal.js"; + +export type DoubleColumnForm = Array; + +export type DoubleColumnFormSection = { + title: TranslatedString; + description?: TranslatedString; + fields: UIFormField[]; +}; + +/** + * Constrain the type with the ui props + */ +type FieldType = { + group: Parameters[0]; + caption: Parameters[0]; + array: Parameters>[0]; + file: Parameters>[0]; + selectOne: Parameters>[0]; + selectMultiple: Parameters>[0]; + text: Parameters>[0]; + textArea: Parameters>[0]; + choiceStacked: Parameters>[0]; + choiceHorizontal: Parameters>[0]; + date: Parameters>[0]; + integer: Parameters>[0]; + amount: Parameters>[0]; +}; + +/** + * List all the form fields so typescript can type-check the form instance + */ +export type UIFormField = + | { type: "group"; props: FieldType["group"] } + | { type: "caption"; props: FieldType["caption"] } + | { type: "array"; props: FieldType["array"] } + | { type: "file"; props: FieldType["file"] } + | { type: "amount"; props: FieldType["amount"] } + | { type: "selectOne"; props: FieldType["selectOne"] } + | { type: "selectMultiple"; props: FieldType["selectMultiple"] } + | { type: "text"; props: FieldType["text"] } + | { type: "textArea"; props: FieldType["textArea"] } + | { type: "choiceStacked"; props: FieldType["choiceStacked"] } + | { type: "choiceHorizontal"; props: FieldType["choiceHorizontal"] } + | { type: "integer"; props: FieldType["integer"] } + | { type: "date"; props: FieldType["date"] }; + +type FieldComponentFunction = ( + props: FieldType[key], +) => VNode; + +type UIFormFieldMap = { + [key in keyof FieldType]: FieldComponentFunction; +}; + +/** + * Maps input type with component implementation + */ +const UIFormConfiguration: UIFormFieldMap = { + group: Group, + caption: Caption, + //@ts-ignore + array: InputArray, + text: InputText, + //@ts-ignore + file: InputFile, + textArea: InputTextArea, + //@ts-ignore + date: InputDate, + //@ts-ignore + choiceStacked: InputChoiceStacked, + //@ts-ignore + choiceHorizontal: InputChoiceHorizontal, + integer: InputInteger, + //@ts-ignore + selectOne: InputSelectOne, + //@ts-ignore + selectMultiple: InputSelectMultiple, + //@ts-ignore + amount: InputAmount, +}; + +export function RenderAllFieldsByUiConfig({ + fields, +}: { + fields: UIFormField[]; +}): VNode { + return create( + Fragment, + {}, + fields.map((field, i) => { + const Component = UIFormConfiguration[ + field.type + ] as FieldComponentFunction; + return Component(field.props); + }), + ); +} + +type FormSet = { + Provider: typeof FormProvider; + InputLine: () => typeof InputLine; + InputChoiceHorizontal: () => typeof InputChoiceHorizontal< + T, + K + >; +}; +export function createNewForm() { + const res: FormSet = { + Provider: FormProvider, + InputLine: () => InputLine, + InputChoiceHorizontal: () => InputChoiceHorizontal, + }; + return { + Provider: res.Provider, + InputLine: res.InputLine(), + InputChoiceHorizontal: res.InputChoiceHorizontal(), + }; +} -- cgit v1.2.3