@sealcode/sealgen 0.19.3 → 0.19.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/@types/forms/controls/hybrid.d.ts +10 -0
- package/@types/forms/controls/simple-input.d.ts +1 -0
- package/@types/forms/fields/field.d.ts +2 -0
- package/@types/forms/fields/fields.d.ts +2 -0
- package/@types/forms/fields/get-field-for-sealious.d.ts +2 -1
- package/@types/forms/fields/phone-number-with-country-code.d.ts +10 -0
- package/@types/forms/fields/phone-number.d.ts +17 -0
- package/@types/forms/fields/simple-form-field.d.ts +2 -0
- package/@types/utils/input-wrapper.d.ts +2 -0
- package/lib/forms/controls/checkboxed-list-input.js +2 -2
- package/lib/forms/controls/dropdown.js +3 -3
- package/lib/forms/controls/hybrid.js +41 -0
- package/lib/forms/controls/multiple-files.js +3 -1
- package/lib/forms/controls/simple-input.js +7 -2
- package/lib/forms/controls/single-reference.js +1 -1
- package/lib/forms/controls/table.js +1 -1
- package/lib/forms/fields/boolean.js +1 -1
- package/lib/forms/fields/checkboxed-list.js +3 -1
- package/lib/forms/fields/coordinates.js +1 -1
- package/lib/forms/fields/date.js +4 -1
- package/lib/forms/fields/datetime.js +1 -1
- package/lib/forms/fields/deep-reverse-single-reference-table.js +1 -1
- package/lib/forms/fields/email.js +4 -1
- package/lib/forms/fields/field.js +4 -0
- package/lib/forms/fields/fields.js +2 -0
- package/lib/forms/fields/get-field-for-sealious.js +8 -0
- package/lib/forms/fields/phone-number-with-country-code.js +50 -0
- package/lib/forms/fields/phone-number.js +33 -0
- package/lib/forms/fields/regexp.js +1 -1
- package/lib/forms/fields/simple-form-field.js +6 -2
- package/lib/forms/fields/single-reference.js +1 -1
- package/lib/forms/fields/structured-array.js +1 -1
- package/lib/forms/fields/table.js +1 -1
- package/lib/utils/input-wrapper.js +13 -0
- package/package.json +2 -1
- package/src/forms/controls/checkboxed-list-input.ts +4 -2
- package/src/forms/controls/dropdown.ts +3 -3
- package/src/forms/controls/hybrid.ts +44 -0
- package/src/forms/controls/multiple-files.ts +5 -1
- package/src/forms/controls/simple-input.ts +9 -1
- package/src/forms/controls/single-reference.ts +1 -1
- package/src/forms/controls/table.ts +1 -1
- package/src/forms/fields/boolean.ts +1 -1
- package/src/forms/fields/checkboxed-list.ts +3 -1
- package/src/forms/fields/coordinates.ts +1 -1
- package/src/forms/fields/date.ts +4 -1
- package/src/forms/fields/datetime.ts +1 -1
- package/src/forms/fields/deep-reverse-single-reference-table.ts +1 -1
- package/src/forms/fields/email.ts +4 -1
- package/src/forms/fields/field.ts +6 -0
- package/src/forms/fields/fields.ts +2 -0
- package/src/forms/fields/get-field-for-sealious.ts +58 -100
- package/src/forms/fields/phone-number-with-country-code.ts +59 -0
- package/src/forms/fields/phone-number.ts +39 -0
- package/src/forms/fields/regexp.ts +1 -1
- package/src/forms/fields/simple-form-field.ts +8 -2
- package/src/forms/fields/single-reference.ts +1 -1
- package/src/forms/fields/structured-array.ts +1 -1
- package/src/forms/fields/table.ts +1 -1
- package/src/utils/input-wrapper.ts +14 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { FlatTemplatable, tempstream } from "tempstream";
|
|
2
|
+
import { FormControlContext } from "./form-control.js";
|
|
3
|
+
import { FormFieldControl } from "./form-field-control.js";
|
|
4
|
+
import { FormField } from "../fields/field.js";
|
|
5
|
+
import { FormDataValue } from "../form-types.js";
|
|
6
|
+
import { autoWrapInput } from "../../utils/input-wrapper.js";
|
|
7
|
+
|
|
8
|
+
export class Hybrid extends FormFieldControl {
|
|
9
|
+
constructor(
|
|
10
|
+
public main_field: FormField,
|
|
11
|
+
public subfields: Record<string, FormField>
|
|
12
|
+
) {
|
|
13
|
+
super(Object.values(subfields));
|
|
14
|
+
for (const [field_name, field] of Object.entries(subfields)) {
|
|
15
|
+
field.setName(`${main_field.name}[${field_name}]`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async render(fctx: FormControlContext): Promise<FlatTemplatable> {
|
|
20
|
+
const raw_values = (fctx.data.raw_values[this.main_field.name] ||
|
|
21
|
+
{}) as Record<string, FormDataValue>;
|
|
22
|
+
const new_fctx = new FormControlContext(
|
|
23
|
+
fctx.ctx,
|
|
24
|
+
{
|
|
25
|
+
raw_values,
|
|
26
|
+
messages: [],
|
|
27
|
+
field_messages: {},
|
|
28
|
+
},
|
|
29
|
+
[],
|
|
30
|
+
fctx.field_name_prefix,
|
|
31
|
+
fctx.form_id,
|
|
32
|
+
fctx.validate
|
|
33
|
+
);
|
|
34
|
+
return tempstream`<fieldset><legend>${this.main_field.label || this.main_field.name}</legend>${Object.values(
|
|
35
|
+
this.subfields
|
|
36
|
+
).map(
|
|
37
|
+
async (subfield) =>
|
|
38
|
+
tempstream`${autoWrapInput(
|
|
39
|
+
subfield,
|
|
40
|
+
await subfield.getControl().render(new_fctx)
|
|
41
|
+
)}`
|
|
42
|
+
)}</fieldset>`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -231,7 +231,11 @@ export class MultipleFiles extends FormFieldControl {
|
|
|
231
231
|
"multiple-files",
|
|
232
232
|
["multiple-files", this.field.name, ...this.getClassModifiers()],
|
|
233
233
|
tempstream /* HTML */ `
|
|
234
|
-
<label
|
|
234
|
+
<label
|
|
235
|
+
>${this.options.label ||
|
|
236
|
+
this.field.label ||
|
|
237
|
+
this.field.name}</label
|
|
238
|
+
>
|
|
235
239
|
<ul class="multiple-files__list">
|
|
236
240
|
${files.map(([item, file]) =>
|
|
237
241
|
this.renderFileItem(item, file)
|
|
@@ -6,6 +6,7 @@ import { FormField } from "../fields/field.js";
|
|
|
6
6
|
import { FormDataValue } from "../form-types.js";
|
|
7
7
|
import { FormControlContext } from "./form-control.js";
|
|
8
8
|
import { FormFieldControl } from "./form-field-control.js";
|
|
9
|
+
import { SimpleFormField } from "../fields/simple-form-field.js";
|
|
9
10
|
|
|
10
11
|
export type SimpleInputOptions = {
|
|
11
12
|
id?: string;
|
|
@@ -19,6 +20,7 @@ export type SimpleInputOptions = {
|
|
|
19
20
|
step?: number;
|
|
20
21
|
suffix?: string;
|
|
21
22
|
pattern?: string;
|
|
23
|
+
inputmode?: string;
|
|
22
24
|
};
|
|
23
25
|
|
|
24
26
|
export class SimpleInput<
|
|
@@ -48,7 +50,7 @@ export class SimpleInput<
|
|
|
48
50
|
getLabel(): string {
|
|
49
51
|
return this.options.label != undefined
|
|
50
52
|
? this.options.label
|
|
51
|
-
: this.field.name;
|
|
53
|
+
: this.field.label || this.field.name;
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
getID(): string {
|
|
@@ -56,6 +58,9 @@ export class SimpleInput<
|
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
getPlaceholder(): string {
|
|
61
|
+
if (this.field instanceof SimpleFormField && this.field.placeholder) {
|
|
62
|
+
return this.field.placeholder;
|
|
63
|
+
}
|
|
59
64
|
return this.options.placeholder === ""
|
|
60
65
|
? ""
|
|
61
66
|
: this.options.placeholder || this.getType();
|
|
@@ -83,6 +88,9 @@ export class SimpleInput<
|
|
|
83
88
|
...(!this.options.autocomplete ? [["autocomplete", "off"]] : []),
|
|
84
89
|
...(this.options.step ? [["step", this.options.step]] : []),
|
|
85
90
|
["aria-invalid", String(!valid)],
|
|
91
|
+
...(this.options.inputmode
|
|
92
|
+
? [["inputmode", this.options.inputmode]]
|
|
93
|
+
: []),
|
|
86
94
|
]) as Record<string, string>;
|
|
87
95
|
}
|
|
88
96
|
|
|
@@ -159,7 +159,7 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
159
159
|
: []),
|
|
160
160
|
].join(" ")}"
|
|
161
161
|
>
|
|
162
|
-
<label>${this.options.label}</label>
|
|
162
|
+
<label>${this.options.label || this.table_field.label}</label>
|
|
163
163
|
<div class="table__wrapper">
|
|
164
164
|
<table>
|
|
165
165
|
<tbody>
|
|
@@ -68,7 +68,7 @@ export class Boolean<Required extends boolean> extends FormField<
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
public getControl(): Checkbox {
|
|
71
|
-
return new Checkbox(this, { label: this.name });
|
|
71
|
+
return new Checkbox(this, { label: this.label || this.name });
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
async getSealiousCreateValue(fctx: FormControlContext): Promise<boolean> {
|
package/src/forms/fields/date.ts
CHANGED
|
@@ -30,7 +30,10 @@ export class DateField<Required extends boolean> extends SimpleFormField<
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
getControl(): SimpleInput<SimpleInputOptions> {
|
|
33
|
-
return new SimpleInput(this, {
|
|
33
|
+
return new SimpleInput(this, {
|
|
34
|
+
label: this.label || this.name,
|
|
35
|
+
type: this.type,
|
|
36
|
+
});
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
async getSealiousCreateValue(
|
|
@@ -56,7 +56,7 @@ export class DeepReverseSingleReferenceTable extends Table<
|
|
|
56
56
|
|
|
57
57
|
getControl(): TableControl<any> {
|
|
58
58
|
return new TableControl(this, {
|
|
59
|
-
label: this.name,
|
|
59
|
+
label: this.label || this.name,
|
|
60
60
|
allow_adding: false,
|
|
61
61
|
subfield_controls: {
|
|
62
62
|
selected: this.columns.selected.getControl(),
|
|
@@ -66,6 +66,7 @@ export abstract class FormField<
|
|
|
66
66
|
SealiousValue = any,
|
|
67
67
|
> {
|
|
68
68
|
name: string;
|
|
69
|
+
label: string;
|
|
69
70
|
constructor(public readonly required: Required) {}
|
|
70
71
|
predicate: Predicate = predicates.unknown;
|
|
71
72
|
mapToFilter: (parsed: ParsedValue) => unknown = (value) => value;
|
|
@@ -77,6 +78,11 @@ export abstract class FormField<
|
|
|
77
78
|
return this;
|
|
78
79
|
}
|
|
79
80
|
|
|
81
|
+
setLabel(label: string): this {
|
|
82
|
+
this.label = label;
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
|
|
80
86
|
public async _validate(
|
|
81
87
|
ctx: Context,
|
|
82
88
|
value: ParsedValue
|
|
@@ -20,6 +20,8 @@ export * from "./markdown.js";
|
|
|
20
20
|
export * from "./multiple-files.js";
|
|
21
21
|
export * from "./number.js";
|
|
22
22
|
export * from "./password.js";
|
|
23
|
+
export * from "./phone-number.js";
|
|
24
|
+
export * from "./phone-number-with-country-code.js";
|
|
23
25
|
export * from "./pick-from-list-sealious.js";
|
|
24
26
|
export * from "./pick-from-list.js";
|
|
25
27
|
export * from "./regexp.js";
|
|
@@ -37,107 +37,58 @@ import extract_fields_from_collection, {
|
|
|
37
37
|
import { EnumMultipleSealious } from "./enum-multiple-sealious.js";
|
|
38
38
|
import { URLField } from "./url.js";
|
|
39
39
|
import { Image } from "./image.js";
|
|
40
|
+
import { PhoneNumberWithCountryCode } from "./phone-number-with-country-code.js";
|
|
40
41
|
|
|
41
|
-
export type SealiousToFormField<T> =
|
|
42
|
-
? BooleanField<false>
|
|
43
|
-
: T extends SealiousFieldTypes.Color
|
|
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
|
-
: T extends SealiousFieldTypes.ReverseSingleReference
|
|
92
|
-
? TextBasedSimpleField<
|
|
93
|
-
false,
|
|
94
|
-
SimpleInput
|
|
95
|
-
>
|
|
96
|
-
: T extends SealiousFieldTypes.SecretToken
|
|
97
|
-
? TextBasedSimpleField<
|
|
98
|
-
false,
|
|
99
|
-
SimpleInput
|
|
100
|
-
>
|
|
101
|
-
: T extends SealiousFieldTypes.SettableBy<
|
|
102
|
-
infer R
|
|
103
|
-
>
|
|
104
|
-
? SealiousToFormField<R>
|
|
105
|
-
: T extends SealiousFieldTypes.SingleReference
|
|
106
|
-
? SingleReference<
|
|
107
|
-
Collection,
|
|
108
|
-
boolean,
|
|
109
|
-
T
|
|
110
|
-
>
|
|
111
|
-
: T extends SealiousFieldTypes.Text
|
|
112
|
-
? Text<false>
|
|
113
|
-
: T extends SealiousFieldTypes.Username
|
|
114
|
-
? CollectionField<
|
|
115
|
-
SealiousFieldTypes.Username,
|
|
116
|
-
false
|
|
117
|
-
>
|
|
118
|
-
: T extends SealiousFieldTypes.ValueExistingInCollection
|
|
119
|
-
? SimpleFormField<false>
|
|
120
|
-
: T extends SealiousFieldTypes.ValueNotExistingInCollection
|
|
121
|
-
? SimpleFormField<false>
|
|
122
|
-
: T extends SealiousRequiredField<
|
|
123
|
-
any,
|
|
124
|
-
any,
|
|
125
|
-
any
|
|
126
|
-
>
|
|
127
|
-
? SimpleFormField<false>
|
|
128
|
-
: T extends SealiousFieldTypes.Url
|
|
129
|
-
? URLField<false>
|
|
130
|
-
: T extends SealiousFieldTypes.Money
|
|
131
|
-
? SimpleFormField<false>
|
|
132
|
-
: T extends SealiousFieldTypes.Markdown
|
|
133
|
-
? Markdown<false>
|
|
134
|
-
: T extends SealiousFieldTypes.Coordinates
|
|
135
|
-
? Coordinates<false>
|
|
136
|
-
: T extends SealiousFieldTypes.StructuredArray<
|
|
137
|
-
infer R
|
|
138
|
-
>
|
|
139
|
-
? StructuredArrayField<R>
|
|
140
|
-
: TextBasedSimpleField<any>;
|
|
42
|
+
export type SealiousToFormField<T> =
|
|
43
|
+
T extends SealiousFieldTypes.Boolean ? BooleanField<false>
|
|
44
|
+
: T extends SealiousFieldTypes.Color ? Color<false>
|
|
45
|
+
: T extends SealiousFieldTypes.ControlAccess<infer R> ?
|
|
46
|
+
SealiousToFormField<R>
|
|
47
|
+
: T extends SealiousFieldTypes.Date ? DateField<false>
|
|
48
|
+
: T extends SealiousFieldTypes.DateTime ? DateTime<false>
|
|
49
|
+
: T extends SealiousFieldTypes.DeepReverseSingleReference ?
|
|
50
|
+
DeepReverseSingleReferenceList | DeepReverseSingleReferenceTable
|
|
51
|
+
: T extends SealiousFieldTypes.DisallowUpdate<any, any, any, infer R> ?
|
|
52
|
+
SealiousToFormField<R>
|
|
53
|
+
: T extends SealiousFieldTypes.Email ? EmailField<false>
|
|
54
|
+
: T extends SealiousFieldTypes.Enum<any> ? PickFromListSealious<false>
|
|
55
|
+
: T extends SealiousFieldTypes.EnumMultiple<infer R> ?
|
|
56
|
+
R extends string[] ?
|
|
57
|
+
EnumMultipleSealious<R>
|
|
58
|
+
: TextBasedSimpleField<false>
|
|
59
|
+
: T extends SealiousFieldTypes.File ? File<false>
|
|
60
|
+
: T extends SealiousFieldTypes.Float ? Float<false>
|
|
61
|
+
: T extends SealiousFieldTypes.HTML ? HTML<false>
|
|
62
|
+
: T extends SealiousFieldTypes.Image ? Image<false>
|
|
63
|
+
: T extends SealiousFieldTypes.Int ? Int<false>
|
|
64
|
+
: T extends SealiousFieldTypes.JsonObject ? JSONField<false>
|
|
65
|
+
: T extends SealiousFieldTypes.JDD ?
|
|
66
|
+
TextBasedSimpleField<false, SimpleInput>
|
|
67
|
+
: T extends SealiousFieldTypes.Password ? Password<false>
|
|
68
|
+
: T extends SealiousFieldTypes.PhoneNumber ?
|
|
69
|
+
PhoneNumberWithCountryCode<false>
|
|
70
|
+
: T extends SealiousFieldTypes.ReverseSingleReference ?
|
|
71
|
+
TextBasedSimpleField<false, SimpleInput>
|
|
72
|
+
: T extends SealiousFieldTypes.SecretToken ?
|
|
73
|
+
TextBasedSimpleField<false, SimpleInput>
|
|
74
|
+
: T extends SealiousFieldTypes.SettableBy<infer R> ? SealiousToFormField<R>
|
|
75
|
+
: T extends SealiousFieldTypes.SingleReference ?
|
|
76
|
+
SingleReference<Collection, boolean, T>
|
|
77
|
+
: T extends SealiousFieldTypes.Text ? Text<false>
|
|
78
|
+
: T extends SealiousFieldTypes.Username ?
|
|
79
|
+
CollectionField<SealiousFieldTypes.Username, false>
|
|
80
|
+
: T extends SealiousFieldTypes.ValueExistingInCollection ?
|
|
81
|
+
SimpleFormField<false>
|
|
82
|
+
: T extends SealiousFieldTypes.ValueNotExistingInCollection ?
|
|
83
|
+
SimpleFormField<false>
|
|
84
|
+
: T extends SealiousRequiredField<any, any, any> ? SimpleFormField<false>
|
|
85
|
+
: T extends SealiousFieldTypes.Url ? URLField<false>
|
|
86
|
+
: T extends SealiousFieldTypes.Money ? SimpleFormField<false>
|
|
87
|
+
: T extends SealiousFieldTypes.Markdown ? Markdown<false>
|
|
88
|
+
: T extends SealiousFieldTypes.Coordinates ? Coordinates<false>
|
|
89
|
+
: T extends SealiousFieldTypes.StructuredArray<infer R> ?
|
|
90
|
+
StructuredArrayField<R>
|
|
91
|
+
: TextBasedSimpleField<any>;
|
|
141
92
|
|
|
142
93
|
export function sealiousToFormField<SF extends SealiousField<any>>(
|
|
143
94
|
sealious_field: SF
|
|
@@ -227,6 +178,11 @@ export function sealiousToFormField<SF extends SealiousField<any>>(
|
|
|
227
178
|
if (sealious_field instanceof SealiousFieldTypes.Password) {
|
|
228
179
|
return new Password(sealious_field.required) as SealiousToFormField<SF>;
|
|
229
180
|
}
|
|
181
|
+
if (sealious_field instanceof SealiousFieldTypes.PhoneNumber) {
|
|
182
|
+
return new PhoneNumberWithCountryCode(
|
|
183
|
+
sealious_field.required
|
|
184
|
+
) as SealiousToFormField<SF>;
|
|
185
|
+
}
|
|
230
186
|
if (sealious_field instanceof SealiousFieldTypes.SettableBy) {
|
|
231
187
|
return sealiousToFormField(
|
|
232
188
|
sealious_field.virtual_field
|
|
@@ -308,6 +264,8 @@ export async function sealiousFieldInfoToFormField(
|
|
|
308
264
|
return new JSONField(field_info.is_required);
|
|
309
265
|
case "password":
|
|
310
266
|
return new Password(field_info.is_required);
|
|
267
|
+
case "phone-number":
|
|
268
|
+
return new PhoneNumberWithCountryCode(field_info.is_required);
|
|
311
269
|
case "single-reference":
|
|
312
270
|
return new SingleReference(false, {} as any);
|
|
313
271
|
case "text":
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as countryCodes from "country-codes-list";
|
|
2
|
+
import { Context } from "koa";
|
|
3
|
+
import { FieldTypes as SealiousFieldTypes } from "sealious";
|
|
4
|
+
import { FormControl } from "../controls/controls.js";
|
|
5
|
+
import { Hybrid } from "../controls/hybrid.js";
|
|
6
|
+
import { FormDataValue } from "../form-types.js";
|
|
7
|
+
import { FieldParseResult, FormField } from "./field.js";
|
|
8
|
+
import { PickFromListField } from "./pick-from-list.js";
|
|
9
|
+
import { PhoneNumberWithoutCountryCode } from "./phone-number.js";
|
|
10
|
+
|
|
11
|
+
export class PhoneNumberWithCountryCode<
|
|
12
|
+
Required extends boolean,
|
|
13
|
+
> extends FormField<Required, SealiousFieldTypes.PhoneNumberValue> {
|
|
14
|
+
public getEmptyValue(): SealiousFieldTypes.PhoneNumberValue {
|
|
15
|
+
return new SealiousFieldTypes.PhoneNumberValue("48", "0000000");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async parse(
|
|
19
|
+
ctx: Context,
|
|
20
|
+
raw_value: FormDataValue
|
|
21
|
+
): Promise<FieldParseResult<SealiousFieldTypes.PhoneNumberValue>> {
|
|
22
|
+
try {
|
|
23
|
+
return {
|
|
24
|
+
parsable: true,
|
|
25
|
+
parsed_value: SealiousFieldTypes.PhoneNumberValue.fromInput(
|
|
26
|
+
ctx.$context,
|
|
27
|
+
raw_value
|
|
28
|
+
),
|
|
29
|
+
error: null,
|
|
30
|
+
};
|
|
31
|
+
} catch (e) {
|
|
32
|
+
return {
|
|
33
|
+
parsable: false,
|
|
34
|
+
parsed_value: null,
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
36
|
+
error: e.message as string,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
getControl(): FormControl {
|
|
42
|
+
return new Hybrid(this, {
|
|
43
|
+
country_code: new PickFromListField(true, async () =>
|
|
44
|
+
countryCodes
|
|
45
|
+
.all()
|
|
46
|
+
.sort((a, b) =>
|
|
47
|
+
a.countryCallingCode < b.countryCallingCode ? -1 : 1
|
|
48
|
+
)
|
|
49
|
+
.map((code) => ({
|
|
50
|
+
value: code.countryCallingCode,
|
|
51
|
+
label: "+" + code.countryCallingCode + " " + code.flag,
|
|
52
|
+
}))
|
|
53
|
+
).setLabel("Country code"),
|
|
54
|
+
number: new PhoneNumberWithoutCountryCode(true).setLabel(
|
|
55
|
+
"Phone number"
|
|
56
|
+
),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Context } from "koa";
|
|
2
|
+
import { FormControl, SimpleInput } from "../controls/controls.js";
|
|
3
|
+
import { FormDataValue } from "../form-types.js";
|
|
4
|
+
import { FormField } from "./field.js";
|
|
5
|
+
|
|
6
|
+
export class PhoneNumberWithoutCountryCode<
|
|
7
|
+
Required extends boolean,
|
|
8
|
+
> extends FormField<Required, string> {
|
|
9
|
+
public getEmptyValue(): string {
|
|
10
|
+
return "000 000 000";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async parse(ctx: Context, raw_value: FormDataValue) {
|
|
14
|
+
if (typeof raw_value == "string") {
|
|
15
|
+
return {
|
|
16
|
+
parsable: <const>true,
|
|
17
|
+
parsed_value: raw_value
|
|
18
|
+
.replaceAll(/[^0-9]/, "")
|
|
19
|
+
.replace(/(\d{3})(?=\d)/g, "$1 ")
|
|
20
|
+
.trim(),
|
|
21
|
+
error: null,
|
|
22
|
+
};
|
|
23
|
+
} else {
|
|
24
|
+
return {
|
|
25
|
+
parsable: <const>false,
|
|
26
|
+
parsed_value: null,
|
|
27
|
+
error: "Expected string",
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
getControl(): FormControl {
|
|
33
|
+
return new SimpleInput(this, {
|
|
34
|
+
inputmode: "tel",
|
|
35
|
+
type: "text",
|
|
36
|
+
placeholder: "123 456 789",
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -59,7 +59,7 @@ export class RegExpField<Required extends boolean> extends FormField<
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
public getControl(): SimpleInput {
|
|
62
|
-
return new SimpleInput(this, { label: this.name });
|
|
62
|
+
return new SimpleInput(this, { label: this.label || this.name });
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
async getSealiousCreateValue(fctx: FormControlContext): Promise<string> {
|
|
@@ -14,6 +14,7 @@ export abstract class SimpleFormField<
|
|
|
14
14
|
Parsed = string,
|
|
15
15
|
> extends FormField<Required, Parsed, DefaultControl> {
|
|
16
16
|
predicate = predicates.string;
|
|
17
|
+
public placeholder: string;
|
|
17
18
|
|
|
18
19
|
constructor(
|
|
19
20
|
required: Required,
|
|
@@ -32,6 +33,11 @@ export abstract class SimpleFormField<
|
|
|
32
33
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
33
34
|
return String(value) as FormDataValue;
|
|
34
35
|
}
|
|
36
|
+
|
|
37
|
+
setPlaceholder(placeholder: string) {
|
|
38
|
+
this.placeholder = placeholder;
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
export class TextBasedSimpleField<
|
|
@@ -76,7 +82,7 @@ export class TextBasedSimpleField<
|
|
|
76
82
|
|
|
77
83
|
getControl(): DefaultControl {
|
|
78
84
|
return new SimpleInput(this, {
|
|
79
|
-
label: this.name,
|
|
85
|
+
label: this.label || this.name,
|
|
80
86
|
type: this.type,
|
|
81
87
|
}) as unknown as DefaultControl;
|
|
82
88
|
}
|
|
@@ -117,7 +123,7 @@ export class NumberBasedSimpleField<
|
|
|
117
123
|
|
|
118
124
|
getControl(): DefaultControl {
|
|
119
125
|
return new SimpleInput(this, {
|
|
120
|
-
label: this.name,
|
|
126
|
+
label: this.label || this.name,
|
|
121
127
|
type: this.type,
|
|
122
128
|
}) as unknown as DefaultControl;
|
|
123
129
|
}
|
|
@@ -13,7 +13,7 @@ export class SingleReference<
|
|
|
13
13
|
> extends CollectionField<F, Required> {
|
|
14
14
|
getControl(): SingleReferenceDropdown<TargetCollection, F, Required> {
|
|
15
15
|
return new SingleReferenceDropdown(this, {
|
|
16
|
-
label: this.name,
|
|
16
|
+
label: this.label || this.name,
|
|
17
17
|
getLabel: (item) => item.id,
|
|
18
18
|
});
|
|
19
19
|
}
|
|
@@ -55,7 +55,7 @@ export class StructuredArray<
|
|
|
55
55
|
SealiousFields[name]
|
|
56
56
|
>;
|
|
57
57
|
}>(this as any, {
|
|
58
|
-
label: this.name,
|
|
58
|
+
label: this.label || this.name,
|
|
59
59
|
subfield_controls: Object.fromEntries(
|
|
60
60
|
Object.entries(this.columns).map(([column_name, subfield]) => [
|
|
61
61
|
column_name as keyof SealiousFields,
|
|
@@ -98,7 +98,7 @@ export class Table<F extends Record<string, FormField>> extends FormField<
|
|
|
98
98
|
|
|
99
99
|
getControl(): TableControl<F> {
|
|
100
100
|
return new TableControl<F>(this, {
|
|
101
|
-
label: this.name,
|
|
101
|
+
label: this.label || this.name,
|
|
102
102
|
subfield_controls: Object.fromEntries(
|
|
103
103
|
Object.entries(this.columns).map(([column_name, field]) => [
|
|
104
104
|
column_name as keyof F,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { FlatTemplatable, tempstream } from "tempstream";
|
|
2
|
+
import { FormField } from "../index.js";
|
|
3
|
+
import { toKebabCase } from "js-convert-case";
|
|
2
4
|
|
|
3
5
|
export function getRequiredClass(isRequired: boolean): string {
|
|
4
6
|
return isRequired ? "required" : "";
|
|
@@ -21,3 +23,15 @@ export async function inputWrapper(
|
|
|
21
23
|
${input}
|
|
22
24
|
</div>`;
|
|
23
25
|
}
|
|
26
|
+
|
|
27
|
+
export async function autoWrapInput(field: FormField, input: FlatTemplatable) {
|
|
28
|
+
return inputWrapper(
|
|
29
|
+
toKebabCase(field.constructor.name),
|
|
30
|
+
[
|
|
31
|
+
`type--` + toKebabCase(field.constructor.name),
|
|
32
|
+
`name--` + toKebabCase(field.name),
|
|
33
|
+
getRequiredClass(field.required),
|
|
34
|
+
],
|
|
35
|
+
input
|
|
36
|
+
);
|
|
37
|
+
}
|