import { Context } from "koa"; import { FlatTemplatable } from "tempstream"; import { attribute } from "../../sanitize.js"; import { getRequiredClass, inputWrapper } from "../../utils/input-wrapper.js"; import { FormField } from "../fields/field.js"; import { FormDataValue } from "../form-types.js"; import { FormControlContext } from "./form-control.js"; import { FormFieldControl } from "./form-field-control.js"; export type TickableOptions = { id?: string; name?: string; label?: string; hide_errors?: boolean; readonly?: boolean; default_value: T; }; export abstract class Tickable extends FormFieldControl { constructor( public field: FormField, public options: TickableOptions ) { super([field]); } public type: "checkbox" | "radio"; abstract getValueAttribute( ctx: Context, data: Record, value: T ): string; abstract isChecked( ctx: Context, data: Record, value: T ): boolean; makeInputID( ctx: Context, data: Record, value: T ): string { const value_attr = this.getValueAttribute(ctx, data, value); return ( this.options.id || this.field.name + (value_attr ? "--" + value_attr : "") ); } getWrapperClasses( ctx: Context, data: Record, value: T ): string[] { return [ this.makeInputID(ctx, data, value), this.type, this.field.name.replaceAll(/\W/g, "-"), getRequiredClass(this.field.required), ...(this.isChecked(ctx, data, value) ? ["checked"] : []), ]; } async render(fctx: FormControlContext): Promise { const { parsed: _parsed, valid, message, } = await this.field.getParsedValue( fctx.ctx, fctx.data.raw_values, true ); const field_message = fctx.data.field_messages[this.field.name]; const parsed = _parsed === null ? this.options.default_value : _parsed; const value = this.getValueAttribute( fctx.ctx, fctx.data.raw_values, parsed ); const id = this.makeInputID(fctx.ctx, fctx.data.raw_values, parsed); const label = this.options.label != undefined ? this.options.label : this.field.name; const readonly = this.options.readonly || false; const required = this.field.required; return inputWrapper( this.type, this.getWrapperClasses(fctx.ctx, fctx.data.raw_values, parsed), /* HTML */ ` ${( (~valid || !!field_message) && !this.options.hide_errors && fctx.validate ) ? `
${Array.from(new Set([message, field_message.message].filter((e) => !!e))).join(" • ")}
` : ""} ` ); } }