@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.
Files changed (60) hide show
  1. package/@types/forms/controls/hybrid.d.ts +10 -0
  2. package/@types/forms/controls/simple-input.d.ts +1 -0
  3. package/@types/forms/fields/field.d.ts +2 -0
  4. package/@types/forms/fields/fields.d.ts +2 -0
  5. package/@types/forms/fields/get-field-for-sealious.d.ts +2 -1
  6. package/@types/forms/fields/phone-number-with-country-code.d.ts +10 -0
  7. package/@types/forms/fields/phone-number.d.ts +17 -0
  8. package/@types/forms/fields/simple-form-field.d.ts +2 -0
  9. package/@types/utils/input-wrapper.d.ts +2 -0
  10. package/lib/forms/controls/checkboxed-list-input.js +2 -2
  11. package/lib/forms/controls/dropdown.js +3 -3
  12. package/lib/forms/controls/hybrid.js +41 -0
  13. package/lib/forms/controls/multiple-files.js +3 -1
  14. package/lib/forms/controls/simple-input.js +7 -2
  15. package/lib/forms/controls/single-reference.js +1 -1
  16. package/lib/forms/controls/table.js +1 -1
  17. package/lib/forms/fields/boolean.js +1 -1
  18. package/lib/forms/fields/checkboxed-list.js +3 -1
  19. package/lib/forms/fields/coordinates.js +1 -1
  20. package/lib/forms/fields/date.js +4 -1
  21. package/lib/forms/fields/datetime.js +1 -1
  22. package/lib/forms/fields/deep-reverse-single-reference-table.js +1 -1
  23. package/lib/forms/fields/email.js +4 -1
  24. package/lib/forms/fields/field.js +4 -0
  25. package/lib/forms/fields/fields.js +2 -0
  26. package/lib/forms/fields/get-field-for-sealious.js +8 -0
  27. package/lib/forms/fields/phone-number-with-country-code.js +50 -0
  28. package/lib/forms/fields/phone-number.js +33 -0
  29. package/lib/forms/fields/regexp.js +1 -1
  30. package/lib/forms/fields/simple-form-field.js +6 -2
  31. package/lib/forms/fields/single-reference.js +1 -1
  32. package/lib/forms/fields/structured-array.js +1 -1
  33. package/lib/forms/fields/table.js +1 -1
  34. package/lib/utils/input-wrapper.js +13 -0
  35. package/package.json +2 -1
  36. package/src/forms/controls/checkboxed-list-input.ts +4 -2
  37. package/src/forms/controls/dropdown.ts +3 -3
  38. package/src/forms/controls/hybrid.ts +44 -0
  39. package/src/forms/controls/multiple-files.ts +5 -1
  40. package/src/forms/controls/simple-input.ts +9 -1
  41. package/src/forms/controls/single-reference.ts +1 -1
  42. package/src/forms/controls/table.ts +1 -1
  43. package/src/forms/fields/boolean.ts +1 -1
  44. package/src/forms/fields/checkboxed-list.ts +3 -1
  45. package/src/forms/fields/coordinates.ts +1 -1
  46. package/src/forms/fields/date.ts +4 -1
  47. package/src/forms/fields/datetime.ts +1 -1
  48. package/src/forms/fields/deep-reverse-single-reference-table.ts +1 -1
  49. package/src/forms/fields/email.ts +4 -1
  50. package/src/forms/fields/field.ts +6 -0
  51. package/src/forms/fields/fields.ts +2 -0
  52. package/src/forms/fields/get-field-for-sealious.ts +58 -100
  53. package/src/forms/fields/phone-number-with-country-code.ts +59 -0
  54. package/src/forms/fields/phone-number.ts +39 -0
  55. package/src/forms/fields/regexp.ts +1 -1
  56. package/src/forms/fields/simple-form-field.ts +8 -2
  57. package/src/forms/fields/single-reference.ts +1 -1
  58. package/src/forms/fields/structured-array.ts +1 -1
  59. package/src/forms/fields/table.ts +1 -1
  60. 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>${this.options.label || this.field.name}</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
 
@@ -13,7 +13,7 @@ export class SingleReferenceDropdown<
13
13
  public options: DropdownOptions & {
14
14
  getLabel?: (item: CollectionItem<Collection>) => string;
15
15
  } = {
16
- label: field.name,
16
+ label: field.label || field.name,
17
17
  autosubmit: false,
18
18
  autocomplete: true,
19
19
  }
@@ -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> {
@@ -74,6 +74,8 @@ export class CheckboxedListField<
74
74
  }
75
75
 
76
76
  getControl(): CheckboxedListInput<Values> {
77
- return new CheckboxedListInput(this, { label: this.name });
77
+ return new CheckboxedListInput(this, {
78
+ label: this.label || this.name,
79
+ });
78
80
  }
79
81
  }
@@ -55,7 +55,7 @@ export class Coordinates<
55
55
 
56
56
  getControl(): DefaultControl {
57
57
  return new SimpleInput(this, {
58
- label: this.name,
58
+ label: this.label || this.name,
59
59
  type: this.type,
60
60
  }) as unknown as DefaultControl;
61
61
  }
@@ -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, { label: this.name, type: this.type });
33
+ return new SimpleInput(this, {
34
+ label: this.label || this.name,
35
+ type: this.type,
36
+ });
34
37
  }
35
38
 
36
39
  async getSealiousCreateValue(
@@ -45,7 +45,7 @@ export class DateTime<Required extends boolean> extends SimpleFormField<
45
45
 
46
46
  getControl(): SimpleInput {
47
47
  return new SimpleInput(this, {
48
- label: this.name,
48
+ label: this.label || this.name,
49
49
  type: this.type,
50
50
  });
51
51
  }
@@ -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(),
@@ -24,6 +24,9 @@ export class EmailField<
24
24
  }
25
25
 
26
26
  public getControl(): SimpleInput {
27
- return new SimpleInput(this, { label: this.name, type: "email" });
27
+ return new SimpleInput(this, {
28
+ label: this.label || this.name,
29
+ type: "email",
30
+ });
28
31
  }
29
32
  }
@@ -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> = T extends SealiousFieldTypes.Boolean
42
- ? BooleanField<false>
43
- : T extends SealiousFieldTypes.Color
44
- ? Color<false>
45
- : T extends SealiousFieldTypes.ControlAccess<infer R>
46
- ? SealiousToFormField<R>
47
- : T extends SealiousFieldTypes.Date
48
- ? DateField<false>
49
- : T extends SealiousFieldTypes.DateTime
50
- ? DateTime<false>
51
- : T extends SealiousFieldTypes.DeepReverseSingleReference
52
- ?
53
- | DeepReverseSingleReferenceList
54
- | DeepReverseSingleReferenceTable
55
- : T extends SealiousFieldTypes.DisallowUpdate<
56
- any,
57
- any,
58
- any,
59
- infer R
60
- >
61
- ? SealiousToFormField<R>
62
- : T extends SealiousFieldTypes.Email
63
- ? EmailField<false>
64
- : T extends SealiousFieldTypes.Enum<any>
65
- ? PickFromListSealious<false>
66
- : T extends SealiousFieldTypes.EnumMultiple<
67
- infer R
68
- >
69
- ? R extends string[]
70
- ? EnumMultipleSealious<R>
71
- : TextBasedSimpleField<false>
72
- : T extends SealiousFieldTypes.File
73
- ? File<false>
74
- : T extends SealiousFieldTypes.Float
75
- ? Float<false>
76
- : T extends SealiousFieldTypes.HTML
77
- ? HTML<false>
78
- : T extends SealiousFieldTypes.Image
79
- ? Image<false>
80
- : T extends SealiousFieldTypes.Int
81
- ? Int<false>
82
- : T extends SealiousFieldTypes.JsonObject
83
- ? JSONField<false>
84
- : T extends SealiousFieldTypes.JDD
85
- ? TextBasedSimpleField<
86
- false,
87
- SimpleInput
88
- >
89
- : T extends SealiousFieldTypes.Password
90
- ? Password<false>
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
+ }