UNPKG

svelte-hook-form

Version:
123 lines (106 loc) 3 kB
import { get, type Readable } from "svelte/store"; import type { FieldState, FieldStore, ValidationResult, ValidationRule } from "./types"; export class FormField { constructor( private readonly store: FieldStore, private readonly rules: ValidationRule[], private readonly bail: boolean ) {} /** * Returns a readonly field state. * * @returns {Readable<FieldState>} state of the field. */ get state() { return get(this.store); } /** * Observe the field state. * * @returns {Readable<FieldState>} state of the field. * * @example * ```svelte * <script lang="ts"> * const state$ = watch("text"); * state$.subscribe((v) => { * console.log("State =>", v); * }); * </script> * ``` */ get watch(): Readable<FieldState> { const { subscribe } = this.store; return { subscribe }; } /** * Update the current field state. * * @param {Partial<FieldState>} state * * @example * ```ts * field.setState({ valid: true }); * ``` */ setState(state: Partial<FieldState>) { this.store.update((v) => ({ ...v, ...state })); } validate = (value: any = undefined): Promise<FieldState> => { const promises: Promise<ValidationResult>[] = []; const len = this.rules.length; let newState = Object.assign(this.state, { errors: [] }); value = value || newState.value; // If it's empty rules, it will always return `true` if (len == 0) { newState = Object.assign(newState, { value, valid: true }); this.setState(newState); return Promise.resolve(newState); } newState = Object.assign(newState, { // dirty: v.dirty ? true : soft ? false : true, pending: true, value }); this.setState(newState); // Setup validation rules and pass in field value let i = 0; for (i = 0; i < len; i++) { const { validate, params } = this.rules[i]; promises.push(validate(value, params)); } if (this.bail) { return new Promise(async (resolve) => { for (i = 0; i < len; i++) { const result = await promises[i]; if (result !== true) { newState = Object.assign(newState, { pending: false, errors: [result], valid: false }); this.setState(newState); resolve(newState); return; } } newState = Object.assign(newState, { pending: false, valid: false }); this.setState(newState); resolve(newState); }); } return Promise.all(promises).then((result: ValidationResult[]) => { const errors = <string[]>result.filter((v: ValidationResult) => v !== true); newState = Object.assign(newState, { pending: false, errors, valid: errors.length === 0 }); this.setState(newState); return Promise.resolve(newState); }); }; }