UNPKG

@thi.ng/rdom-forms

Version:

Data-driven declarative & extensible HTML form generation

328 lines 9.68 kB
import type { Fn, Predicate } from "@thi.ng/api"; import type { Attribs, FormAttribs, InputAttribs, InputCheckboxAttribs, InputFileAttribs, InputNumericAttribs, InputRadioAttribs, InputSubmitAttribs, InputTextAttribs, SelectAttribs, StringAttrib, TextAreaAttribs } from "@thi.ng/hiccup-html"; import type { ComponentLike } from "@thi.ng/rdom"; import type { ISubscriber, ISubscription } from "@thi.ng/rstream"; export interface CommonAttribs { wrapperAttribs: Partial<Attribs>; labelAttribs: Partial<Attribs>; descAttribs: Partial<Attribs>; } export interface FormItem { /** * Value/widget type identifier. Used by {@link compileForm} to delegate */ type: string; /** * Attrib overrides for the actual input element. */ attribs?: Partial<Attribs>; } export interface Form { type: "form"; items: FormItem[]; attribs?: Partial<FormAttribs>; } export interface Container extends FormItem { type: "container"; items: FormItem[]; } export interface Custom extends Pick<FormItem, "type"> { type: "custom"; body: ComponentLike; } export interface Group extends FormItem { type: "group"; items: FormItem[]; label?: StringAttrib | false; } export interface Value extends FormItem, Partial<CommonAttribs> { id: string; name?: string; /** * If false, no `<label>` element will be generated for this control and the * {@link Value.desc} value will be unused. */ label?: StringAttrib | false; desc?: any; required?: boolean; /** * If true, no input/change event handlers will be generated and the * `readonly` attribute will be set on the input DOM element. */ readonly?: boolean; attribs?: Partial<InputAttribs>; } export interface HiddenValue extends Omit<FormItem, "attribs"> { id?: string; name: string; value: StringAttrib; } export interface WithPresets<T> { /** * Array of possible preset values. */ list?: T[]; } export interface Num extends Value, WithPresets<number> { type: "num"; min?: number; max?: number; placeholder?: StringAttrib; size?: number; step?: number | "any"; value?: ISubscription<number, number>; attribs?: Partial<InputNumericAttribs>; } export interface Range extends Omit<Num, "type" | "placeholder" | "size"> { type: "range"; vlabel?: boolean | number | Fn<number, string>; } export interface Str extends Value, WithPresets<string> { type: "str"; min?: number; max?: number; pattern?: string | RegExp | Predicate<string>; placeholder?: StringAttrib; size?: number; value?: ISubscription<string, string>; attribs?: Partial<InputTextAttribs>; } export interface Email extends Omit<Str, "type"> { type: "email"; autocomplete?: boolean; } export interface Phone extends Omit<Str, "type"> { type: "tel"; autocomplete?: boolean; } export interface UrlVal extends Omit<Str, "type"> { type: "url"; } export interface Password extends Omit<Str, "type"> { type: "password"; autocomplete?: boolean; } export interface Text extends Value { type: "text"; cols?: number; rows?: number; placeholder?: StringAttrib; value?: ISubscription<string, string>; attribs?: Partial<TextAreaAttribs>; } export interface Color extends Value, WithPresets<string> { type: "color"; value?: ISubscription<string, string>; } export interface DateTime extends Value, WithPresets<string> { type: "dateTime"; min?: string; max?: string; step?: number; value?: ISubscription<string, string>; } export interface DateVal extends Omit<DateTime, "type"> { type: "date"; } export interface Time extends Omit<DateTime, "type"> { type: "time"; } export interface Week extends Omit<DateTime, "type" | "list"> { type: "week"; } export interface Month extends Omit<DateTime, "type" | "list"> { type: "month"; } export interface Select<T> extends Value { items: (T | SelectItem<T> | SelectItemGroup<T>)[]; value?: ISubscription<T, T>; attribs?: Partial<Omit<SelectAttribs, "multiple">>; } export interface SelectItemGroup<T> { name: string; items: (T | SelectItem<T>)[]; } export interface SelectItem<T> { value: T; label?: string; desc?: string; } export interface SelectStr<T extends string = string> extends Select<T> { type: "selectStr"; } export interface SelectNum<T extends number = number> extends Select<T> { type: "selectNum"; } export interface MultiSelect<T> extends Value { items: (T | SelectItem<T> | SelectItemGroup<T>)[]; value?: ISubscription<T[], T[]>; size?: number; attribs?: Partial<Omit<SelectAttribs, "multiple">>; } export interface MultiSelectStr<T extends string = string> extends MultiSelect<T> { type: "multiSelectStr"; } export interface MultiSelectNum<T extends number = number> extends MultiSelect<T> { type: "multiSelectNum"; } export interface Toggle extends Value { type: "toggle"; value?: ISubscription<boolean, boolean>; attribs?: Partial<InputCheckboxAttribs>; } export interface Trigger extends Value { type: "trigger"; title: StringAttrib; value?: ISubscriber<boolean>; } export interface Submit extends Omit<Value, "required" | "readonly"> { type: "submit"; title: StringAttrib; value?: ISubscriber<boolean>; attribs?: Partial<InputSubmitAttribs>; } export interface Reset extends Omit<Value, "required" | "readonly"> { type: "submit"; title: StringAttrib; value?: ISubscriber<boolean>; } export interface Radio<T> extends Value { items: (T | SelectItem<T>)[]; value?: ISubscription<T, T>; attribs?: Partial<InputRadioAttribs>; } export interface RadioNum extends Radio<number> { type: "radioNum"; } export interface RadioStr extends Radio<string> { type: "radioStr"; } export interface FileVal extends Value { type: "file"; accept?: string[]; capture?: InputFileAttribs["capture"]; value?: ISubscriber<File>; attribs?: Partial<InputFileAttribs>; } export interface MultiFileVal extends Value { type: "multiFile"; accept?: string[]; value?: ISubscriber<FileList>; attribs?: Partial<InputFileAttribs>; } type KnownTypes = Color | Container | DateTime | DateVal | Email | FileVal | Group | Month | MultiFileVal | MultiSelectNum | MultiSelectStr | Num | Password | Phone | Range | SelectNum | SelectStr | Str | Text | Time | Toggle | Trigger | UrlVal | Week; /** * Type specific attribute overrides */ export interface TypeAttribs extends Record<KnownTypes["type"], Partial<Attribs>> { form: Partial<FormAttribs>; /** * Attribs for {@link group} label elements */ groupLabel: Partial<Attribs>; /** * Attribs for the actual {@link radio} `<input>` element */ radio: Partial<InputRadioAttribs>; /** * Attribs for the outermost {@link radio} group wrapper element (incl. main * group label) */ radioWrapper: Partial<Attribs>; /** * Attribs for the wrapper element only containing the {@link radio} items. */ radioItems: Partial<Attribs>; /** * Attribs for the wrapper element of a single {@link radio} item (incl. * input element and its label) */ radioItem: Partial<Attribs>; /** * Attribs for a single {@link radio} item's label */ radioItemLabel: Partial<Attribs>; /** * Attribs for {@link range} label elements */ rangeLabel: Partial<Attribs>; /** * Attribs for the wrapper element of a single {@link range} widget (incl. * input element and optional value label) */ rangeWrapper: Partial<Attribs>; [id: string]: Partial<Attribs>; } export interface FormOpts extends CommonAttribs { /** * ID prefix to prepend for all {@link FormItem}s. Needed if the a form is * to used in multiple places at the same time. */ prefix: string; /** * Type specific behavior options. */ behaviors: Partial<BehaviorOpts>; /** * Type specific attrib overrides */ typeAttribs: Partial<TypeAttribs>; } export interface BehaviorOpts { /** * If false, no label elements will be generated. * * @defaultValue true */ labels: boolean; /** * If false, no `value` attributes and event handlers will be generated, * even if a `value` option has been specified. * * @defaultValue true */ values: boolean; /** * Unless false, {@link range} widgets will emit `oninput` events, if false * only `onchange` events. * * @defaultValue true */ rangeOnInput: boolean; /** * Unless false, {@link str}-like widgets will emit `oninput` events, if * false only `onchange` events. * * @defaultValue true */ strOnInput: boolean; /** * Unless false, {@link text} elements will emit `oninput` events, if false * only `onchange` events. * * @defaultValue true */ textOnInput: boolean; /** * If true, the label for individual radio items will come before the actual * input element. By default, the order is reversed. * * @defaultValue false */ radioLabelBefore: boolean; /** * Number of fractional digits for range sliders. * * @defaultValue 2 */ rangeLabelFmt: number | Fn<number, string>; /** * If true, the label for toggle widgets will come before the actual * input element. By default, the order is reversed. * * @defaultValue false */ toggleLabelBefore: boolean; } export {}; //# sourceMappingURL=api.d.ts.map