@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,10 @@
1
+ import { FlatTemplatable } 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
+ export declare class Hybrid extends FormFieldControl {
6
+ main_field: FormField;
7
+ subfields: Record<string, FormField>;
8
+ constructor(main_field: FormField, subfields: Record<string, FormField>);
9
+ render(fctx: FormControlContext): Promise<FlatTemplatable>;
10
+ }
@@ -16,6 +16,7 @@ export type SimpleInputOptions = {
16
16
  step?: number;
17
17
  suffix?: string;
18
18
  pattern?: string;
19
+ inputmode?: string;
19
20
  };
20
21
  export declare class SimpleInput<Options extends SimpleInputOptions = SimpleInputOptions> extends FormFieldControl {
21
22
  field: FormField<boolean, any>;
@@ -32,11 +32,13 @@ export type FieldParseResult<T> = {
32
32
  export declare abstract class FormField<Required extends boolean = boolean, ParsedValue = unknown, DefaultFormControl extends FormControl = FormControl, SealiousValue = any> {
33
33
  readonly required: Required;
34
34
  name: string;
35
+ label: string;
35
36
  constructor(required: Required);
36
37
  predicate: Predicate;
37
38
  mapToFilter: (parsed: ParsedValue) => unknown;
38
39
  init(): Promise<void>;
39
40
  setName(name: string): this;
41
+ setLabel(label: string): this;
40
42
  _validate(ctx: Context, value: ParsedValue): Promise<FormFieldValidationResponse>;
41
43
  abstract getEmptyValue(): ParsedValue;
42
44
  isValueValid(_ctx: Context, _value: ParsedValue): Promise<FormFieldValidationResponse>;
@@ -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";
@@ -26,6 +26,7 @@ import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.j
26
26
  import { EnumMultipleSealious } from "./enum-multiple-sealious.js";
27
27
  import { URLField } from "./url.js";
28
28
  import { Image } from "./image.js";
29
- export type SealiousToFormField<T> = T extends SealiousFieldTypes.Boolean ? BooleanField<false> : T extends SealiousFieldTypes.Color ? Color<false> : T extends SealiousFieldTypes.ControlAccess<infer R> ? SealiousToFormField<R> : T extends SealiousFieldTypes.Date ? DateField<false> : T extends SealiousFieldTypes.DateTime ? DateTime<false> : T extends SealiousFieldTypes.DeepReverseSingleReference ? DeepReverseSingleReferenceList | DeepReverseSingleReferenceTable : T extends SealiousFieldTypes.DisallowUpdate<any, any, any, infer R> ? SealiousToFormField<R> : T extends SealiousFieldTypes.Email ? EmailField<false> : T extends SealiousFieldTypes.Enum<any> ? PickFromListSealious<false> : T extends SealiousFieldTypes.EnumMultiple<infer R> ? R extends string[] ? EnumMultipleSealious<R> : TextBasedSimpleField<false> : T extends SealiousFieldTypes.File ? File<false> : T extends SealiousFieldTypes.Float ? Float<false> : T extends SealiousFieldTypes.HTML ? HTML<false> : T extends SealiousFieldTypes.Image ? Image<false> : T extends SealiousFieldTypes.Int ? Int<false> : T extends SealiousFieldTypes.JsonObject ? JSONField<false> : T extends SealiousFieldTypes.JDD ? TextBasedSimpleField<false, SimpleInput> : T extends SealiousFieldTypes.Password ? Password<false> : T extends SealiousFieldTypes.ReverseSingleReference ? TextBasedSimpleField<false, SimpleInput> : T extends SealiousFieldTypes.SecretToken ? TextBasedSimpleField<false, SimpleInput> : T extends SealiousFieldTypes.SettableBy<infer R> ? SealiousToFormField<R> : T extends SealiousFieldTypes.SingleReference ? SingleReference<Collection, boolean, T> : T extends SealiousFieldTypes.Text ? Text<false> : T extends SealiousFieldTypes.Username ? CollectionField<SealiousFieldTypes.Username, false> : T extends SealiousFieldTypes.ValueExistingInCollection ? SimpleFormField<false> : T extends SealiousFieldTypes.ValueNotExistingInCollection ? SimpleFormField<false> : T extends SealiousRequiredField<any, any, any> ? SimpleFormField<false> : T extends SealiousFieldTypes.Url ? URLField<false> : T extends SealiousFieldTypes.Money ? SimpleFormField<false> : T extends SealiousFieldTypes.Markdown ? Markdown<false> : T extends SealiousFieldTypes.Coordinates ? Coordinates<false> : T extends SealiousFieldTypes.StructuredArray<infer R> ? StructuredArrayField<R> : TextBasedSimpleField<any>;
29
+ import { PhoneNumberWithCountryCode } from "./phone-number-with-country-code.js";
30
+ export type SealiousToFormField<T> = T extends SealiousFieldTypes.Boolean ? BooleanField<false> : T extends SealiousFieldTypes.Color ? Color<false> : T extends SealiousFieldTypes.ControlAccess<infer R> ? SealiousToFormField<R> : T extends SealiousFieldTypes.Date ? DateField<false> : T extends SealiousFieldTypes.DateTime ? DateTime<false> : T extends SealiousFieldTypes.DeepReverseSingleReference ? DeepReverseSingleReferenceList | DeepReverseSingleReferenceTable : T extends SealiousFieldTypes.DisallowUpdate<any, any, any, infer R> ? SealiousToFormField<R> : T extends SealiousFieldTypes.Email ? EmailField<false> : T extends SealiousFieldTypes.Enum<any> ? PickFromListSealious<false> : T extends SealiousFieldTypes.EnumMultiple<infer R> ? R extends string[] ? EnumMultipleSealious<R> : TextBasedSimpleField<false> : T extends SealiousFieldTypes.File ? File<false> : T extends SealiousFieldTypes.Float ? Float<false> : T extends SealiousFieldTypes.HTML ? HTML<false> : T extends SealiousFieldTypes.Image ? Image<false> : T extends SealiousFieldTypes.Int ? Int<false> : T extends SealiousFieldTypes.JsonObject ? JSONField<false> : T extends SealiousFieldTypes.JDD ? TextBasedSimpleField<false, SimpleInput> : T extends SealiousFieldTypes.Password ? Password<false> : T extends SealiousFieldTypes.PhoneNumber ? PhoneNumberWithCountryCode<false> : T extends SealiousFieldTypes.ReverseSingleReference ? TextBasedSimpleField<false, SimpleInput> : T extends SealiousFieldTypes.SecretToken ? TextBasedSimpleField<false, SimpleInput> : T extends SealiousFieldTypes.SettableBy<infer R> ? SealiousToFormField<R> : T extends SealiousFieldTypes.SingleReference ? SingleReference<Collection, boolean, T> : T extends SealiousFieldTypes.Text ? Text<false> : T extends SealiousFieldTypes.Username ? CollectionField<SealiousFieldTypes.Username, false> : T extends SealiousFieldTypes.ValueExistingInCollection ? SimpleFormField<false> : T extends SealiousFieldTypes.ValueNotExistingInCollection ? SimpleFormField<false> : T extends SealiousRequiredField<any, any, any> ? SimpleFormField<false> : T extends SealiousFieldTypes.Url ? URLField<false> : T extends SealiousFieldTypes.Money ? SimpleFormField<false> : T extends SealiousFieldTypes.Markdown ? Markdown<false> : T extends SealiousFieldTypes.Coordinates ? Coordinates<false> : T extends SealiousFieldTypes.StructuredArray<infer R> ? StructuredArrayField<R> : TextBasedSimpleField<any>;
30
31
  export declare function sealiousToFormField<SF extends SealiousField<any>>(sealious_field: SF): SealiousToFormField<SF>;
31
32
  export declare function sealiousFieldInfoToFormField(field_info: ExtractedFieldInfo): Promise<FormField>;
@@ -0,0 +1,10 @@
1
+ import { Context } from "koa";
2
+ import { FieldTypes as SealiousFieldTypes } from "sealious";
3
+ import { FormControl } from "../controls/controls.js";
4
+ import { FormDataValue } from "../form-types.js";
5
+ import { FieldParseResult, FormField } from "./field.js";
6
+ export declare class PhoneNumberWithCountryCode<Required extends boolean> extends FormField<Required, SealiousFieldTypes.PhoneNumberValue> {
7
+ getEmptyValue(): SealiousFieldTypes.PhoneNumberValue;
8
+ parse(ctx: Context, raw_value: FormDataValue): Promise<FieldParseResult<SealiousFieldTypes.PhoneNumberValue>>;
9
+ getControl(): FormControl;
10
+ }
@@ -0,0 +1,17 @@
1
+ import { Context } from "koa";
2
+ import { FormControl } from "../controls/controls.js";
3
+ import { FormDataValue } from "../form-types.js";
4
+ import { FormField } from "./field.js";
5
+ export declare class PhoneNumberWithoutCountryCode<Required extends boolean> extends FormField<Required, string> {
6
+ getEmptyValue(): string;
7
+ parse(ctx: Context, raw_value: FormDataValue): Promise<{
8
+ parsable: true;
9
+ parsed_value: string;
10
+ error: null;
11
+ } | {
12
+ parsable: false;
13
+ parsed_value: null;
14
+ error: string;
15
+ }>;
16
+ getControl(): FormControl;
17
+ }
@@ -8,8 +8,10 @@ import { FormControlContext } from "../controls/form-control.js";
8
8
  export declare abstract class SimpleFormField<Required extends boolean, DefaultControl extends FormControl = SimpleInput, Parsed = string> extends FormField<Required, Parsed, DefaultControl> {
9
9
  type: string;
10
10
  predicate: import("@sealcode/ts-predicates").Predicate<string>;
11
+ placeholder: string;
11
12
  constructor(required: Required, type?: string);
12
13
  sealiousValueToForm(_ctx: Context, value: unknown): Promise<FormDataValue>;
14
+ setPlaceholder(placeholder: string): this;
13
15
  }
14
16
  export declare class TextBasedSimpleField<Required extends boolean, DefaultControl extends FormControl = SimpleInput> extends SimpleFormField<Required, DefaultControl, string | null> {
15
17
  parse(_: Context, raw_value: FormDataValue): Promise<FieldParseResult<string>>;
@@ -1,3 +1,5 @@
1
1
  import { FlatTemplatable } from "tempstream";
2
+ import { FormField } from "../index.js";
2
3
  export declare function getRequiredClass(isRequired: boolean): string;
3
4
  export declare function inputWrapper(type: string, modifiers: string[], input: FlatTemplatable): Promise<string>;
5
+ export declare function autoWrapInput(field: FormField, input: FlatTemplatable): Promise<string>;
@@ -2,7 +2,7 @@ import { tempstream } from "tempstream";
2
2
  import { getRequiredClass, inputWrapper } from "../../utils/input-wrapper.js";
3
3
  import { FormFieldControl } from "./form-field-control.js";
4
4
  class CheckboxedListInput extends FormFieldControl {
5
- constructor(field, options = { label: field.name }) {
5
+ constructor(field, options = { label: field.label || field.name }) {
6
6
  super([field]);
7
7
  this.field = field;
8
8
  this.options = options;
@@ -52,7 +52,7 @@ class CheckboxedListInput extends FormFieldControl {
52
52
  ...this.generateCountBasedClasses(options.length)
53
53
  ],
54
54
  tempstream`<label
55
- >${this.options.label || this.field.name}</label
55
+ >${this.options.label || this.field.label || this.field.name}</label
56
56
  >
57
57
  ${~valid && fctx.validate ? `<div class="input__error">${message}</div>` : ""}
58
58
  <ul>
@@ -3,7 +3,7 @@ import { attribute } from "../../sanitize.js";
3
3
  import { SimpleInput } from "./simple-input.js";
4
4
  class FreeformDropdown extends SimpleInput {
5
5
  constructor(field, _generateOptions, options = {
6
- label: field.name,
6
+ label: field.label || field.name,
7
7
  autosubmit: false,
8
8
  autocomplete: true
9
9
  }) {
@@ -36,7 +36,7 @@ class FreeformDropdown extends SimpleInput {
36
36
  );
37
37
  return (
38
38
  /* HTML */
39
- tempstream`<select ${attributes_str}>
39
+ tempstream`<select ${attributes_str} autocomplete="off">
40
40
  ${Promise.resolve(this.generateOptions(ctx)).then(
41
41
  (options) => options.map(
42
42
  ({ value, label }) => `<option value="${attribute(value)}" ${(value || "") == picked_value ? "selected" : ""}>${label}</option>`
@@ -48,7 +48,7 @@ class FreeformDropdown extends SimpleInput {
48
48
  }
49
49
  class Dropdown extends FreeformDropdown {
50
50
  constructor(field, options = {
51
- label: field.name,
51
+ label: field.label || field.name,
52
52
  autosubmit: false,
53
53
  autocomplete: true
54
54
  }) {
@@ -0,0 +1,41 @@
1
+ import { tempstream } from "tempstream";
2
+ import { FormControlContext } from "./form-control.js";
3
+ import { FormFieldControl } from "./form-field-control.js";
4
+ import { autoWrapInput } from "../../utils/input-wrapper.js";
5
+ class Hybrid extends FormFieldControl {
6
+ constructor(main_field, subfields) {
7
+ super(Object.values(subfields));
8
+ this.main_field = main_field;
9
+ this.subfields = subfields;
10
+ for (const [field_name, field] of Object.entries(subfields)) {
11
+ field.setName(`${main_field.name}[${field_name}]`);
12
+ }
13
+ }
14
+ async render(fctx) {
15
+ const raw_values = fctx.data.raw_values[this.main_field.name] || {};
16
+ const new_fctx = new FormControlContext(
17
+ fctx.ctx,
18
+ {
19
+ raw_values,
20
+ messages: [],
21
+ field_messages: {}
22
+ },
23
+ [],
24
+ fctx.field_name_prefix,
25
+ fctx.form_id,
26
+ fctx.validate
27
+ );
28
+ return tempstream`<fieldset><legend>${this.main_field.label || this.main_field.name}</legend>${Object.values(
29
+ this.subfields
30
+ ).map(
31
+ async (subfield) => tempstream`${autoWrapInput(
32
+ subfield,
33
+ await subfield.getControl().render(new_fctx)
34
+ )}`
35
+ )}</fieldset>`;
36
+ }
37
+ }
38
+ export {
39
+ Hybrid
40
+ };
41
+ //# sourceMappingURL=hybrid.js.map
@@ -164,7 +164,9 @@ class MultipleFiles extends FormFieldControl {
164
164
  "multiple-files",
165
165
  ["multiple-files", this.field.name, ...this.getClassModifiers()],
166
166
  tempstream`
167
- <label>${this.options.label || this.field.name}</label>
167
+ <label
168
+ >${this.options.label || this.field.label || this.field.name}</label
169
+ >
168
170
  <ul class="multiple-files__list">
169
171
  ${files.map(
170
172
  ([item, file]) => this.renderFileItem(item, file)
@@ -2,6 +2,7 @@ import { tempstream } from "tempstream";
2
2
  import { getRequiredClass, inputWrapper } from "../../utils/input-wrapper.js";
3
3
  import { renderAttributes } from "../../utils/render-attributes.js";
4
4
  import { FormFieldControl } from "./form-field-control.js";
5
+ import { SimpleFormField } from "../fields/simple-form-field.js";
5
6
  class SimpleInput extends FormFieldControl {
6
7
  constructor(field, options) {
7
8
  super([field]);
@@ -15,12 +16,15 @@ class SimpleInput extends FormFieldControl {
15
16
  return this.options.type || "text";
16
17
  }
17
18
  getLabel() {
18
- return this.options.label != void 0 ? this.options.label : this.field.name;
19
+ return this.options.label != void 0 ? this.options.label : this.field.label || this.field.name;
19
20
  }
20
21
  getID() {
21
22
  return this.options.id || this.field.name;
22
23
  }
23
24
  getPlaceholder() {
25
+ if (this.field instanceof SimpleFormField && this.field.placeholder) {
26
+ return this.field.placeholder;
27
+ }
24
28
  return this.options.placeholder === "" ? "" : this.options.placeholder || this.getType();
25
29
  }
26
30
  async getInputAttributes(fctx) {
@@ -42,7 +46,8 @@ class SimpleInput extends FormFieldControl {
42
46
  ...required ? [["required", true]] : [],
43
47
  ...!this.options.autocomplete ? [["autocomplete", "off"]] : [],
44
48
  ...this.options.step ? [["step", this.options.step]] : [],
45
- ["aria-invalid", String(!valid)]
49
+ ["aria-invalid", String(!valid)],
50
+ ...this.options.inputmode ? [["inputmode", this.options.inputmode]] : []
46
51
  ]);
47
52
  }
48
53
  async postInput(_) {
@@ -1,7 +1,7 @@
1
1
  import { FreeformDropdown } from "./dropdown.js";
2
2
  class SingleReferenceDropdown extends FreeformDropdown {
3
3
  constructor(field, options = {
4
- label: field.name,
4
+ label: field.label || field.name,
5
5
  autosubmit: false,
6
6
  autocomplete: true
7
7
  }) {
@@ -88,7 +88,7 @@ class Table extends FormControl {
88
88
  ...rows.length >= 20 ? ["form-input__wrapper--options-count--20-or-more"] : []
89
89
  ].join(" ")}"
90
90
  >
91
- <label>${this.options.label}</label>
91
+ <label>${this.options.label || this.table_field.label}</label>
92
92
  <div class="table__wrapper">
93
93
  <table>
94
94
  <tbody>
@@ -44,7 +44,7 @@ class Boolean extends FormField {
44
44
  return false;
45
45
  }
46
46
  getControl() {
47
- return new Checkbox(this, { label: this.name });
47
+ return new Checkbox(this, { label: this.label || this.name });
48
48
  }
49
49
  async getSealiousCreateValue(fctx) {
50
50
  const { parsed } = await this.getParsedValue(
@@ -44,7 +44,9 @@ class CheckboxedListField extends FormField {
44
44
  return {};
45
45
  }
46
46
  getControl() {
47
- return new CheckboxedListInput(this, { label: this.name });
47
+ return new CheckboxedListInput(this, {
48
+ label: this.label || this.name
49
+ });
48
50
  }
49
51
  }
50
52
  export {
@@ -35,7 +35,7 @@ class Coordinates extends SimpleFormField {
35
35
  }
36
36
  getControl() {
37
37
  return new SimpleInput(this, {
38
- label: this.name,
38
+ label: this.label || this.name,
39
39
  type: this.type
40
40
  });
41
41
  }
@@ -15,7 +15,10 @@ class DateField extends SimpleFormField {
15
15
  };
16
16
  }
17
17
  getControl() {
18
- return new SimpleInput(this, { label: this.name, type: this.type });
18
+ return new SimpleInput(this, {
19
+ label: this.label || this.name,
20
+ type: this.type
21
+ });
19
22
  }
20
23
  async getSealiousCreateValue(fctx) {
21
24
  const { parsed } = await this.getParsedValue(
@@ -26,7 +26,7 @@ class DateTime extends SimpleFormField {
26
26
  }
27
27
  getControl() {
28
28
  return new SimpleInput(this, {
29
- label: this.name,
29
+ label: this.label || this.name,
30
30
  type: this.type
31
31
  });
32
32
  }
@@ -31,7 +31,7 @@ class DeepReverseSingleReferenceTable extends Table {
31
31
  }
32
32
  getControl() {
33
33
  return new TableControl(this, {
34
- label: this.name,
34
+ label: this.label || this.name,
35
35
  allow_adding: false,
36
36
  subfield_controls: {
37
37
  selected: this.columns.selected.getControl(),
@@ -17,7 +17,10 @@ class EmailField extends RegExpField {
17
17
  this.error_message = message;
18
18
  }
19
19
  getControl() {
20
- return new SimpleInput(this, { label: this.name, type: "email" });
20
+ return new SimpleInput(this, {
21
+ label: this.label || this.name,
22
+ type: "email"
23
+ });
21
24
  }
22
25
  }
23
26
  export {
@@ -18,6 +18,10 @@ class FormField {
18
18
  this.name = name;
19
19
  return this;
20
20
  }
21
+ setLabel(label) {
22
+ this.label = label;
23
+ return this;
24
+ }
21
25
  async _validate(ctx, value) {
22
26
  if (value === "" || value === null || value === void 0) {
23
27
  if (this.required) {
@@ -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";
@@ -25,6 +25,7 @@ import extract_fields_from_collection from "../../utils/extract-fields-from-coll
25
25
  import { EnumMultipleSealious } from "./enum-multiple-sealious.js";
26
26
  import { URLField } from "./url.js";
27
27
  import { Image } from "./image.js";
28
+ import { PhoneNumberWithCountryCode } from "./phone-number-with-country-code.js";
28
29
  function sealiousToFormField(sealious_field) {
29
30
  if (sealious_field instanceof SealiousFieldTypes.Boolean) {
30
31
  return new BooleanField(
@@ -106,6 +107,11 @@ function sealiousToFormField(sealious_field) {
106
107
  if (sealious_field instanceof SealiousFieldTypes.Password) {
107
108
  return new Password(sealious_field.required);
108
109
  }
110
+ if (sealious_field instanceof SealiousFieldTypes.PhoneNumber) {
111
+ return new PhoneNumberWithCountryCode(
112
+ sealious_field.required
113
+ );
114
+ }
109
115
  if (sealious_field instanceof SealiousFieldTypes.SettableBy) {
110
116
  return sealiousToFormField(
111
117
  sealious_field.virtual_field
@@ -184,6 +190,8 @@ async function sealiousFieldInfoToFormField(field_info) {
184
190
  return new JSONField(field_info.is_required);
185
191
  case "password":
186
192
  return new Password(field_info.is_required);
193
+ case "phone-number":
194
+ return new PhoneNumberWithCountryCode(field_info.is_required);
187
195
  case "single-reference":
188
196
  return new SingleReference(false, {});
189
197
  case "text":
@@ -0,0 +1,50 @@
1
+ import * as countryCodes from "country-codes-list";
2
+ import { FieldTypes as SealiousFieldTypes } from "sealious";
3
+ import { Hybrid } from "../controls/hybrid.js";
4
+ import { FormField } from "./field.js";
5
+ import { PickFromListField } from "./pick-from-list.js";
6
+ import { PhoneNumberWithoutCountryCode } from "./phone-number.js";
7
+ class PhoneNumberWithCountryCode extends FormField {
8
+ getEmptyValue() {
9
+ return new SealiousFieldTypes.PhoneNumberValue("48", "0000000");
10
+ }
11
+ async parse(ctx, raw_value) {
12
+ try {
13
+ return {
14
+ parsable: true,
15
+ parsed_value: SealiousFieldTypes.PhoneNumberValue.fromInput(
16
+ ctx.$context,
17
+ raw_value
18
+ ),
19
+ error: null
20
+ };
21
+ } catch (e) {
22
+ return {
23
+ parsable: false,
24
+ parsed_value: null,
25
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
26
+ error: e.message
27
+ };
28
+ }
29
+ }
30
+ getControl() {
31
+ return new Hybrid(this, {
32
+ country_code: new PickFromListField(
33
+ true,
34
+ async () => countryCodes.all().sort(
35
+ (a, b) => a.countryCallingCode < b.countryCallingCode ? -1 : 1
36
+ ).map((code) => ({
37
+ value: code.countryCallingCode,
38
+ label: "+" + code.countryCallingCode + " " + code.flag
39
+ }))
40
+ ).setLabel("Country code"),
41
+ number: new PhoneNumberWithoutCountryCode(true).setLabel(
42
+ "Phone number"
43
+ )
44
+ });
45
+ }
46
+ }
47
+ export {
48
+ PhoneNumberWithCountryCode
49
+ };
50
+ //# sourceMappingURL=phone-number-with-country-code.js.map
@@ -0,0 +1,33 @@
1
+ import { SimpleInput } from "../controls/controls.js";
2
+ import { FormField } from "./field.js";
3
+ class PhoneNumberWithoutCountryCode extends FormField {
4
+ getEmptyValue() {
5
+ return "000 000 000";
6
+ }
7
+ async parse(ctx, raw_value) {
8
+ if (typeof raw_value == "string") {
9
+ return {
10
+ parsable: true,
11
+ parsed_value: raw_value.replaceAll(/[^0-9]/, "").replace(/(\d{3})(?=\d)/g, "$1 ").trim(),
12
+ error: null
13
+ };
14
+ } else {
15
+ return {
16
+ parsable: false,
17
+ parsed_value: null,
18
+ error: "Expected string"
19
+ };
20
+ }
21
+ }
22
+ getControl() {
23
+ return new SimpleInput(this, {
24
+ inputmode: "tel",
25
+ type: "text",
26
+ placeholder: "123 456 789"
27
+ });
28
+ }
29
+ }
30
+ export {
31
+ PhoneNumberWithoutCountryCode
32
+ };
33
+ //# sourceMappingURL=phone-number.js.map
@@ -37,7 +37,7 @@ class RegExpField extends FormField {
37
37
  return this.default_value || "";
38
38
  }
39
39
  getControl() {
40
- return new SimpleInput(this, { label: this.name });
40
+ return new SimpleInput(this, { label: this.label || this.name });
41
41
  }
42
42
  async getSealiousCreateValue(fctx) {
43
43
  const { parsed } = await this.getParsedValue(
@@ -13,6 +13,10 @@ class SimpleFormField extends FormField {
13
13
  }
14
14
  return String(value);
15
15
  }
16
+ setPlaceholder(placeholder) {
17
+ this.placeholder = placeholder;
18
+ return this;
19
+ }
16
20
  }
17
21
  class TextBasedSimpleField extends SimpleFormField {
18
22
  async parse(_, raw_value) {
@@ -36,7 +40,7 @@ class TextBasedSimpleField extends SimpleFormField {
36
40
  }
37
41
  getControl() {
38
42
  return new SimpleInput(this, {
39
- label: this.name,
43
+ label: this.label || this.name,
40
44
  type: this.type
41
45
  });
42
46
  }
@@ -65,7 +69,7 @@ class NumberBasedSimpleField extends SimpleFormField {
65
69
  }
66
70
  getControl() {
67
71
  return new SimpleInput(this, {
68
- label: this.name,
72
+ label: this.label || this.name,
69
73
  type: this.type
70
74
  });
71
75
  }
@@ -4,7 +4,7 @@ import { toPascalCase } from "js-convert-case";
4
4
  class SingleReference extends CollectionField {
5
5
  getControl() {
6
6
  return new SingleReferenceDropdown(this, {
7
- label: this.name,
7
+ label: this.label || this.name,
8
8
  getLabel: (item) => item.id
9
9
  });
10
10
  }
@@ -18,7 +18,7 @@ class StructuredArray extends Table {
18
18
  }
19
19
  getControl() {
20
20
  return new TableControl(this, {
21
- label: this.name,
21
+ label: this.label || this.name,
22
22
  subfield_controls: Object.fromEntries(
23
23
  Object.entries(this.columns).map(([column_name, subfield]) => [
24
24
  column_name,
@@ -70,7 +70,7 @@ class Table extends FormField {
70
70
  }
71
71
  getControl() {
72
72
  return new TableControl(this, {
73
- label: this.name,
73
+ label: this.label || this.name,
74
74
  subfield_controls: Object.fromEntries(
75
75
  Object.entries(this.columns).map(([column_name, field]) => [
76
76
  column_name,
@@ -1,4 +1,5 @@
1
1
  import { tempstream } from "tempstream";
2
+ import { toKebabCase } from "js-convert-case";
2
3
  function getRequiredClass(isRequired) {
3
4
  return isRequired ? "required" : "";
4
5
  }
@@ -14,7 +15,19 @@ async function inputWrapper(type, modifiers, input) {
14
15
  ${input}
15
16
  </div>`;
16
17
  }
18
+ async function autoWrapInput(field, input) {
19
+ return inputWrapper(
20
+ toKebabCase(field.constructor.name),
21
+ [
22
+ `type--` + toKebabCase(field.constructor.name),
23
+ `name--` + toKebabCase(field.name),
24
+ getRequiredClass(field.required)
25
+ ],
26
+ input
27
+ );
28
+ }
17
29
  export {
30
+ autoWrapInput,
18
31
  getRequiredClass,
19
32
  inputWrapper
20
33
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sealcode/sealgen",
3
- "version": "0.19.3",
3
+ "version": "0.19.5",
4
4
  "description": "Module to automate adding routes and collections to a sealious application",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",
@@ -66,6 +66,7 @@
66
66
  "@sealcode/ts-predicates": "^0.4.3",
67
67
  "chokidar": "^3.6.0",
68
68
  "colord": "^2.9.3",
69
+ "country-codes-list": "^2.0.0",
69
70
  "deepmerge": "^4.3.1",
70
71
  "esbuild": "^0.20.0",
71
72
  "escape-goat": "^4.0.0",
@@ -12,7 +12,7 @@ export class CheckboxedListInput<
12
12
  > extends FormFieldControl {
13
13
  constructor(
14
14
  public field: CheckboxedListField<boolean, Values>,
15
- public options: { label: string } = { label: field.name }
15
+ public options: { label: string } = { label: field.label || field.name }
16
16
  ) {
17
17
  super([field]);
18
18
  }
@@ -67,7 +67,9 @@ export class CheckboxedListInput<
67
67
  ...this.generateCountBasedClasses(options.length),
68
68
  ],
69
69
  tempstream /* HTML */ `<label
70
- >${this.options.label || this.field.name}</label
70
+ >${this.options.label ||
71
+ this.field.label ||
72
+ this.field.name}</label
71
73
  >
72
74
  ${~valid && fctx.validate
73
75
  ? `<div class="input__error">${message}</div>`
@@ -20,7 +20,7 @@ export class FreeformDropdown extends SimpleInput {
20
20
  public field: FormField<boolean, string | null>,
21
21
  public _generateOptions: (ctx: Context) => Promise<DropdownOption[]>,
22
22
  public options: DropdownOptions = {
23
- label: field.name,
23
+ label: field.label || field.name,
24
24
  autosubmit: false,
25
25
  autocomplete: true,
26
26
  }
@@ -61,7 +61,7 @@ export class FreeformDropdown extends SimpleInput {
61
61
  ctx,
62
62
  data
63
63
  );
64
- return /* HTML */ tempstream`<select ${attributes_str}>
64
+ return /* HTML */ tempstream`<select ${attributes_str} autocomplete="off">
65
65
  ${Promise.resolve(this.generateOptions(ctx)).then((options) =>
66
66
  options.map(
67
67
  ({ value, label }) =>
@@ -78,7 +78,7 @@ export class Dropdown extends FreeformDropdown {
78
78
  constructor(
79
79
  public field: PickFromListField<boolean>,
80
80
  public options: DropdownOptions = {
81
- label: field.name,
81
+ label: field.label || field.name,
82
82
  autosubmit: false,
83
83
  autocomplete: true,
84
84
  }