@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,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
|
-
|
|
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
|
|
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(_) {
|
|
@@ -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(
|
package/lib/forms/fields/date.js
CHANGED
|
@@ -15,7 +15,10 @@ class DateField extends SimpleFormField {
|
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
getControl() {
|
|
18
|
-
return new SimpleInput(this, {
|
|
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(
|
|
@@ -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, {
|
|
20
|
+
return new SimpleInput(this, {
|
|
21
|
+
label: this.label || this.name,
|
|
22
|
+
type: "email"
|
|
23
|
+
});
|
|
21
24
|
}
|
|
22
25
|
}
|
|
23
26
|
export {
|
|
@@ -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
|
}
|
|
@@ -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
|
+
"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 ||
|
|
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
|
}
|