1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
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<typeof InputArray>[0];
file: Parameters<typeof InputFile>[0];
selectMultiple: Parameters<typeof InputSelectMultiple>[0];
text: Parameters<typeof InputText>[0];
textArea: Parameters<typeof InputTextArea>[0];
choiceStacked: Parameters<typeof InputChoiceStacked>[0];
date: Parameters<typeof InputDate>[0];
integer: Parameters<typeof InputInteger>[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<key extends keyof FieldType> = (
props: FieldType[key],
) => VNode;
type UIFormFieldMap = {
[key in keyof FieldType]: FieldComponentFunction<key>;
};
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<any>;
const c = structuredClone(field.props);
c.key = i;
return Component(c);
}),
);
}
|