import { is, predicates } from "@sealcode/ts-predicates"; import { Context } from "koa"; import { Dropdown, DropdownOption } from "../controls/dropdown.js"; import { FormFieldValidationResponse } from "./field.js"; import { TextBasedSimpleField } from "./simple-form-field.js"; export class PickFromListField< Required extends boolean, > extends TextBasedSimpleField { constructor( public required: Required, public generateOptions: (ctx: Context) => Promise, public customValidation: ( ctx: Context, value: unknown, instance: PickFromListField ) => Promise = (ctx, value, instance) => instance.valueInList(ctx, value) ) { super(required); } predicate = predicates.string; public isValueValid( ctx: Context, value: string ): Promise { return this.customValidation(ctx, value, this); } async valueInList( ctx: Context, value: unknown ): Promise { const options = await this.generateOptions(ctx); if (!is(value, predicates.string)) { return { valid: false, message: "not a string" }; } if (this.required && !options.map((o) => o.value).includes(value)) { return { valid: false, message: `"${value}" is not one of the options`, }; } return { valid: true, message: "" }; } public getEmptyValue(): string { return ""; } getControl(): Dropdown { return new Dropdown(this); } }