aboutsummaryrefslogtreecommitdiff
path: root/packages/web-util/src/forms/ui-form.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/web-util/src/forms/ui-form.ts')
-rw-r--r--packages/web-util/src/forms/ui-form.ts376
1 files changed, 143 insertions, 233 deletions
diff --git a/packages/web-util/src/forms/ui-form.ts b/packages/web-util/src/forms/ui-form.ts
index ef9ad96e1..d683b15de 100644
--- a/packages/web-util/src/forms/ui-form.ts
+++ b/packages/web-util/src/forms/ui-form.ts
@@ -14,18 +14,18 @@ import {
TalerProtocolTimestamp,
} from "@gnu-taler/taler-util";
-export type FlexibleForm = DoubleColumnForm;
+export type FormConfiguration = DoubleColumnForm;
-export interface DoubleColumnForm {
+export type DoubleColumnForm = {
type: "double-column";
- design: Array<DoubleColumnFormSection>;
+ design: DoubleColumnFormSection[];
// behavior?: (form: Partial<T>) => FormState<T>;
-}
+};
export type DoubleColumnFormSection = {
title: string;
description?: string;
- fields: UIFormFieldConfig[];
+ fields: UIFormElementConfig[];
};
// export interface BaseForm {
@@ -33,92 +33,74 @@ export type DoubleColumnFormSection = {
// threshold: AmountJson;
// }
-export type UIFormFieldConfig =
- | UIFormFieldConfigAbsoluteTime
- | UIFormFieldConfigAmount
- | UIFormFieldConfigArray
- | UIFormFieldConfigCaption
- | UIFormFieldConfigChoiseHorizontal
- | UIFormFieldConfigChoiseStacked
- | UIFormFieldConfigFile
- | UIFormFieldConfigGroup
- | UIFormFieldConfigInteger
- | UIFormFieldConfigSelectMultiple
- | UIFormFieldConfigSelectOne
- | UIFormFieldConfigText
- | UIFormFieldConfigTextArea
- | UIFormFieldConfigToggle;
-
-type UIFormFieldConfigAbsoluteTime = {
+export type UIFormElementConfig =
+ | UIFormElementGroup
+ | UIFormElementCaption
+ | UIFormFieldAbsoluteTime
+ | UIFormFieldAmount
+ | UIFormFieldArray
+ | UIFormFieldChoiseHorizontal
+ | UIFormFieldChoiseStacked
+ | UIFormFieldFile
+ | UIFormFieldInteger
+ | UIFormFieldSelectMultiple
+ | UIFormFieldSelectOne
+ | UIFormFieldText
+ | UIFormFieldTextArea
+ | UIFormFieldToggle;
+
+type UIFormFieldAbsoluteTime = {
type: "absoluteTime";
- properties: UIFormFieldBaseConfig & {
- max?: TalerProtocolTimestamp;
- min?: TalerProtocolTimestamp;
- pattern: string;
- };
-};
+ max?: TalerProtocolTimestamp;
+ min?: TalerProtocolTimestamp;
+ pattern: string;
+} & UIFormFieldBaseConfig;
-type UIFormFieldConfigAmount = {
+type UIFormFieldAmount = {
type: "amount";
- properties: UIFormFieldBaseConfig & {
- max?: Integer;
- min?: Integer;
- currency: string;
- };
-};
+ max?: Integer;
+ min?: Integer;
+ currency: string;
+} & UIFormFieldBaseConfig;
-type UIFormFieldConfigArray = {
+type UIFormFieldArray = {
type: "array";
- properties: UIFormFieldBaseConfig & {
- // id of the field shown when the array is collapsed
- labelFieldId: UIHandlerId;
- fields: UIFormFieldConfig[];
- };
-};
+ // id of the field shown when the array is collapsed
+ labelFieldId: UIHandlerId;
+ fields: UIFormElementConfig[];
+} & UIFormFieldBaseConfig;
-type UIFormFieldConfigCaption = {
- type: "caption";
- properties: UIFieldBaseDescription;
-};
+type UIFormElementCaption = { type: "caption" } & UIFieldElementDescription;
-type UIFormFieldConfigGroup = {
+type UIFormElementGroup = {
type: "group";
- properties: UIFieldBaseDescription & {
- fields: UIFormFieldConfig[];
- };
-};
+ fields: UIFormElementConfig[];
+} & UIFieldElementDescription;
-type UIFormFieldConfigChoiseHorizontal = {
+type UIFormFieldChoiseHorizontal = {
type: "choiceHorizontal";
- properties: UIFormFieldBaseConfig & {
- choices: Array<SelectUiChoice>;
- };
-};
+ choices: Array<SelectUiChoice>;
+} & UIFormFieldBaseConfig;
-type UIFormFieldConfigChoiseStacked = {
+type UIFormFieldChoiseStacked = {
type: "choiceStacked";
- properties: UIFormFieldBaseConfig & {
- choices: Array<SelectUiChoice>;
- };
-};
+ choices: Array<SelectUiChoice>;
+} & UIFormFieldBaseConfig;
-type UIFormFieldConfigFile = {
+type UIFormFieldFile = {
type: "file";
- properties: UIFormFieldBaseConfig & {
- maxBytes?: Integer;
- minBytes?: Integer;
- // comma-separated list of one or more file types
- // https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept#unique_file_type_specifiers
- accept?: string;
- };
-};
-type UIFormFieldConfigInteger = {
+ maxBytes?: Integer;
+ minBytes?: Integer;
+ // comma-separated list of one or more file types
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept#unique_file_type_specifiers
+ accept?: string;
+} & UIFormFieldBaseConfig;
+
+type UIFormFieldInteger = {
type: "integer";
- properties: UIFormFieldBaseConfig & {
- max?: Integer;
- min?: Integer;
- };
-};
+ max?: Integer;
+ min?: Integer;
+} & UIFormFieldBaseConfig;
interface SelectUiChoice {
label: string;
@@ -126,41 +108,30 @@ interface SelectUiChoice {
value: string;
}
-type UIFormFieldConfigSelectMultiple = {
+type UIFormFieldSelectMultiple = {
type: "selectMultiple";
- properties: UIFormFieldBaseConfig & {
- max?: Integer;
- min?: Integer;
- unique?: boolean;
- choices: Array<SelectUiChoice>;
- };
-};
-type UIFormFieldConfigSelectOne = {
+ max?: Integer;
+ min?: Integer;
+ unique?: boolean;
+ choices: Array<SelectUiChoice>;
+} & UIFormFieldBaseConfig;
+
+type UIFormFieldSelectOne = {
type: "selectOne";
- properties: UIFormFieldBaseConfig & {
- choices: Array<SelectUiChoice>;
- };
-};
-type UIFormFieldConfigText = {
- type: "text";
- properties: UIFormFieldBaseConfig;
-};
-type UIFormFieldConfigTextArea = {
- type: "textArea";
- properties: UIFormFieldBaseConfig;
-};
-type UIFormFieldConfigToggle = {
- type: "toggle";
- properties: UIFormFieldBaseConfig;
-};
+ choices: Array<SelectUiChoice>;
+} & UIFormFieldBaseConfig;
+type UIFormFieldText = { type: "text" } & UIFormFieldBaseConfig;
+type UIFormFieldTextArea = { type: "textArea" } & UIFormFieldBaseConfig;
+type UIFormFieldToggle = { type: "toggle" } & UIFormFieldBaseConfig;
-export type UIFieldBaseDescription = {
+export type UIFieldElementDescription = {
/* label if the field, visible for the user */
label: string;
+
/* long text to be shown on user demand */
tooltip?: string;
- /* short text to be shown close to the field */
+ /* short text to be shown close to the field, usually below and dimmer*/
help?: string;
/* name of the field, useful for a11y */
@@ -168,13 +139,15 @@ export type UIFieldBaseDescription = {
/* if the field should be initially hidden */
hidden?: boolean;
+
/* ui element to show before */
addonBeforeId?: string;
+
/* ui element to show after */
addonAfterId?: string;
};
-export type UIFormFieldBaseConfig = UIFieldBaseDescription & {
+export type UIFormFieldBaseConfig = UIFieldElementDescription & {
/* example to be shown inside the field */
placeholder?: string;
@@ -200,7 +173,7 @@ export type UIHandlerId = string & { [__handlerId]: true };
const codecForUiFieldId = codecForString as () => Codec<UIHandlerId>;
const codecForUIFormFieldBaseDescriptionTemplate = <
- T extends UIFieldBaseDescription,
+ T extends UIFieldElementDescription,
>() =>
buildCodecForObject<T>()
.property("addonAfterId", codecOptional(codecForString()))
@@ -221,62 +194,35 @@ const codecForUIFormFieldBaseConfigTemplate = <
.property("required", codecOptional(codecForBoolean()))
.property("placeholder", codecOptional(codecForString()));
-const codecForUIFormFieldBaseConfig = (): Codec<UIFormFieldBaseConfig> =>
- codecForUIFormFieldBaseConfigTemplate().build("UIFieldToggleProperties");
-
-const codecForUIFormFieldAbsoluteTimeConfig = (): Codec<
- UIFormFieldConfigAbsoluteTime["properties"]
-> =>
- codecForUIFormFieldBaseConfigTemplate<
- UIFormFieldConfigAbsoluteTime["properties"]
- >()
+const codecForUiFormFieldAbsoluteTime = (): Codec<UIFormFieldAbsoluteTime> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldAbsoluteTime>()
+ .property("type", codecForConstString("absoluteTime"))
.property("pattern", codecForString())
.property("max", codecOptional(codecForTimestamp))
.property("min", codecOptional(codecForTimestamp))
- .build("UIFormFieldConfigAbsoluteTime.properties");
-
-const codecForUiFormFieldAbsoluteTime =
- (): Codec<UIFormFieldConfigAbsoluteTime> =>
- buildCodecForObject<UIFormFieldConfigAbsoluteTime>()
- .property("type", codecForConstString("absoluteTime"))
- .property("properties", codecForUIFormFieldAbsoluteTimeConfig())
- .build("UIFormFieldConfigAbsoluteTime");
-
-const codecForUIFormFieldAmountConfig = (): Codec<
- UIFormFieldConfigAmount["properties"]
-> =>
- codecForUIFormFieldBaseConfigTemplate<UIFormFieldConfigAmount["properties"]>()
+ .build("UIFormFieldAbsoluteTime");
+
+const codecForUiFormFieldAmount = (): Codec<UIFormFieldAmount> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldAmount>()
+ .property("type", codecForConstString("amount"))
.property("currency", codecForString())
.property("max", codecOptional(codecForNumber()))
.property("min", codecOptional(codecForNumber()))
- .build("UIFormFieldConfigAmount.properties");
-
-const codecForUiFormFieldAmount = (): Codec<UIFormFieldConfigAmount> =>
- buildCodecForObject<UIFormFieldConfigAmount>()
- .property("type", codecForConstString("amount"))
- .property("properties", codecForUIFormFieldAmountConfig())
- .build("UIFormFieldConfigAmount");
+ .build("UIFormFieldAmount");
-const codecForUIFormFieldArrayConfig = (): Codec<
- UIFormFieldConfigArray["properties"]
-> =>
- codecForUIFormFieldBaseConfigTemplate<UIFormFieldConfigArray["properties"]>()
+const codecForUiFormFieldArray = (): Codec<UIFormFieldArray> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldArray>()
+ .property("type", codecForConstString("array"))
.property("labelFieldId", codecForUiFieldId())
+ .property("tooltip", codecOptional(codecForString()))
// eslint-disable-next-line @typescript-eslint/no-use-before-define
.property("fields", codecForList(codecForUiFormField()))
- .build("UIFormFieldConfigArray.properties");
-
-const codecForUiFormFieldArray = (): Codec<UIFormFieldConfigArray> =>
- buildCodecForObject<UIFormFieldConfigArray>()
- .property("type", codecForConstString("array"))
- .property("properties", codecForUIFormFieldArrayConfig())
- .build("UIFormFieldConfigArray");
+ .build("UIFormFieldArray");
-const codecForUiFormFieldCaption = (): Codec<UIFormFieldConfigCaption> =>
- buildCodecForObject<UIFormFieldConfigCaption>()
+const codecForUiFormFieldCaption = (): Codec<UIFormElementCaption> =>
+ codecForUIFormFieldBaseDescriptionTemplate<UIFormElementCaption>()
.property("type", codecForConstString("caption"))
- .property("properties", codecForUIFormFieldBaseConfig())
- .build("UIFormFieldConfigCaption");
+ .build("UIFormFieldCaption");
const codecForUiFormSelectUiChoice = (): Codec<SelectUiChoice> =>
buildCodecForObject<SelectUiChoice>()
@@ -285,111 +231,75 @@ const codecForUiFormSelectUiChoice = (): Codec<SelectUiChoice> =>
.property("value", codecForString())
.build("SelectUiChoice");
-const codecForUIFormFieldWithChoiseConfig = (): Codec<
- UIFormFieldConfigChoiseHorizontal["properties"]
-> =>
- codecForUIFormFieldBaseConfigTemplate<
- UIFormFieldConfigChoiseHorizontal["properties"]
- >()
- .property("choices", codecForList(codecForUiFormSelectUiChoice()))
- .build("UIFormFieldConfigChoiseHorizontal.properties");
-
const codecForUiFormFieldChoiceHorizontal =
- (): Codec<UIFormFieldConfigChoiseHorizontal> =>
- buildCodecForObject<UIFormFieldConfigChoiseHorizontal>()
+ (): Codec<UIFormFieldChoiseHorizontal> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldChoiseHorizontal>()
.property("type", codecForConstString("choiceHorizontal"))
- .property("properties", codecForUIFormFieldWithChoiseConfig())
- .build("UIFormFieldConfigChoiseHorizontal");
-
-const codecForUiFormFieldChoiceStacked =
- (): Codec<UIFormFieldConfigChoiseStacked> =>
- buildCodecForObject<UIFormFieldConfigChoiseStacked>()
- .property("type", codecForConstString("choiceStacked"))
- .property("properties", codecForUIFormFieldWithChoiseConfig())
- .build("UIFormFieldConfigChoiseStacked");
-
-const codecForUIFormFieldFileConfig = (): Codec<
- UIFormFieldConfigFile["properties"]
-> =>
- codecForUIFormFieldBaseConfigTemplate<UIFormFieldConfigFile["properties"]>()
+ .property("choices", codecForList(codecForUiFormSelectUiChoice()))
+ .build("UIFormFieldChoiseHorizontal");
+
+const codecForUiFormFieldChoiceStacked = (): Codec<UIFormFieldChoiseStacked> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldChoiseStacked>()
+ .property("type", codecForConstString("choiceStacked"))
+ .property("choices", codecForList(codecForUiFormSelectUiChoice()))
+ .build("UIFormFieldChoiseStacked");
+
+const codecForUiFormFieldFile = (): Codec<UIFormFieldFile> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldFile>()
+ .property("type", codecForConstString("file"))
.property("accept", codecOptional(codecForString()))
.property("maxBytes", codecOptional(codecForNumber()))
.property("minBytes", codecOptional(codecForNumber()))
- .build("UIFormFieldConfigFile.properties");
+ .build("UIFormFieldFile");
-const codecForUiFormFieldFile = (): Codec<UIFormFieldConfigFile> =>
- buildCodecForObject<UIFormFieldConfigFile>()
- .property("type", codecForConstString("file"))
- .property("properties", codecForUIFormFieldFileConfig())
- .build("UIFormFieldConfigFile");
-
-const codecForUIFormFieldWithFieldsConfig = (): Codec<
- UIFormFieldConfigGroup["properties"]
-> =>
- codecForUIFormFieldBaseDescriptionTemplate<
- UIFormFieldConfigGroup["properties"]
- >()
+const codecForUiFormFieldGroup = (): Codec<UIFormElementGroup> =>
+ codecForUIFormFieldBaseDescriptionTemplate<UIFormElementGroup>()
+ .property("type", codecForConstString("group"))
// eslint-disable-next-line @typescript-eslint/no-use-before-define
.property("fields", codecForList(codecForUiFormField()))
- .build("UIFormFieldConfigGroup.properties");
-
-const codecForUiFormFieldGroup = (): Codec<UIFormFieldConfigGroup> =>
- buildCodecForObject<UIFormFieldConfigGroup>()
- .property("type", codecForConstString("group"))
- .property("properties", codecForUIFormFieldWithFieldsConfig())
.build("UiFormFieldGroup");
-const codecForUiFormFieldInteger = (): Codec<UIFormFieldConfigInteger> =>
- buildCodecForObject<UIFormFieldConfigInteger>()
+const codecForUiFormFieldInteger = (): Codec<UIFormFieldInteger> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldInteger>()
.property("type", codecForConstString("integer"))
- .property("properties", codecForUIFormFieldBaseConfig())
- .build("UIFormFieldConfigInteger");
-
-const codecForUIFormFieldSelectMultipleConfig = (): Codec<
- UIFormFieldConfigSelectMultiple["properties"]
-> =>
- codecForUIFormFieldBaseConfigTemplate<
- UIFormFieldConfigSelectMultiple["properties"]
- >()
+ // .property("properties", codecForUIFormFieldBaseConfig())
.property("max", codecOptional(codecForNumber()))
.property("min", codecOptional(codecForNumber()))
- .property("unique", codecOptional(codecForBoolean()))
- .property("choices", codecForList(codecForUiFormSelectUiChoice()))
- .build("UIFormFieldConfigSelectMultiple.properties");
+ .build("UIFormFieldInteger");
const codecForUiFormFieldSelectMultiple =
- (): Codec<UIFormFieldConfigSelectMultiple> =>
- buildCodecForObject<UIFormFieldConfigSelectMultiple>()
+ (): Codec<UIFormFieldSelectMultiple> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldSelectMultiple>()
.property("type", codecForConstString("selectMultiple"))
- .property("properties", codecForUIFormFieldSelectMultipleConfig())
+ .property("max", codecOptional(codecForNumber()))
+ .property("min", codecOptional(codecForNumber()))
+ .property("unique", codecOptional(codecForBoolean()))
+ .property("choices", codecForList(codecForUiFormSelectUiChoice()))
.build("UiFormFieldSelectMultiple");
-const codecForUiFormFieldSelectOne = (): Codec<UIFormFieldConfigSelectOne> =>
- buildCodecForObject<UIFormFieldConfigSelectOne>()
+const codecForUiFormFieldSelectOne = (): Codec<UIFormFieldSelectOne> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldSelectOne>()
.property("type", codecForConstString("selectOne"))
- .property("properties", codecForUIFormFieldWithChoiseConfig())
- .build("UIFormFieldConfigSelectOne");
+ .property("choices", codecForList(codecForUiFormSelectUiChoice()))
+ .build("UIFormFieldSelectOne");
-const codecForUiFormFieldText = (): Codec<UIFormFieldConfigText> =>
- buildCodecForObject<UIFormFieldConfigText>()
+const codecForUiFormFieldText = (): Codec<UIFormFieldText> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldText>()
.property("type", codecForConstString("text"))
- .property("properties", codecForUIFormFieldBaseConfig())
- .build("UIFormFieldConfigText");
+ .build("UIFormFieldText");
-const codecForUiFormFieldTextArea = (): Codec<UIFormFieldConfigTextArea> =>
- buildCodecForObject<UIFormFieldConfigTextArea>()
+const codecForUiFormFieldTextArea = (): Codec<UIFormFieldTextArea> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldTextArea>()
.property("type", codecForConstString("textArea"))
- .property("properties", codecForUIFormFieldBaseConfig())
- .build("UIFormFieldConfigTextArea");
+ .build("UIFormFieldTextArea");
-const codecForUiFormFieldToggle = (): Codec<UIFormFieldConfigToggle> =>
- buildCodecForObject<UIFormFieldConfigToggle>()
+const codecForUiFormFieldToggle = (): Codec<UIFormFieldToggle> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldToggle>()
.property("type", codecForConstString("toggle"))
- .property("properties", codecForUIFormFieldBaseConfig())
- .build("UIFormFieldConfigToggle");
+ .build("UIFormFieldToggle");
-const codecForUiFormField = (): Codec<UIFormFieldConfig> =>
- buildCodecForUnion<UIFormFieldConfig>()
+const codecForUiFormField = (): Codec<UIFormElementConfig> =>
+ buildCodecForUnion<UIFormElementConfig>()
.discriminateOn("type")
.alternative("array", codecForLazy(codecForUiFormFieldArray))
.alternative("group", codecForLazy(codecForUiFormFieldGroup))
@@ -420,18 +330,18 @@ const codecForDoubleColumnForm = (): Codec<DoubleColumnForm> =>
.property("design", codecForList(codecForDoubleColumnFormSection()))
.build("DoubleColumnForm");
-const codecForFlexibleForm = (): Codec<FlexibleForm> =>
- buildCodecForUnion<FlexibleForm>()
+const codecForFormConfiguration = (): Codec<FormConfiguration> =>
+ buildCodecForUnion<FormConfiguration>()
.discriminateOn("type")
.alternative("double-column", codecForDoubleColumnForm())
- .build<FlexibleForm>("FlexibleForm");
+ .build<FormConfiguration>("FormConfiguration");
const codecForFormMetadata = (): Codec<FormMetadata> =>
buildCodecForObject<FormMetadata>()
.property("label", codecForString())
.property("id", codecForString())
.property("version", codecForNumber())
- .property("config", codecForFlexibleForm())
+ .property("config", codecForFormConfiguration())
.build("FormMetadata");
export const codecForUIForms = (): Codec<UiForms> =>
@@ -443,7 +353,7 @@ export type FormMetadata = {
label: string;
id: string;
version: number;
- config: FlexibleForm;
+ config: FormConfiguration;
};
export interface UiForms {