UNPKG

@smkit/ui

Version:

UI Kit of SberMarketing

125 lines (124 loc) 4.13 kB
import { InputTypes } from './types'; import { DEFAULT_INPUT_SETTINGS, LACK_OF_SCHEMA_ERROR } from './constants'; import { get, writable } from 'svelte/store'; export class Form { inputNames; data; validators; errors; isValid; constructor() { this.inputNames = []; this.data = writable({}); this.validators = {}; this.errors = writable({}); this.isValid = writable(false); } parseInputValue(name) { const value = this.data[name]; const schema = this.validators[name]; if (!schema) throw new Error(LACK_OF_SCHEMA_ERROR); return schema.safeParse(value); } checkFormValidity() { const errors = get(this.errors); const activeErrors = Object.values(errors).filter((err) => err); const isFormValid = activeErrors.length === 0; this.isValid.set(isFormValid); return isFormValid; } setError(name, message) { this.errors.update((v) => ({ ...v, [name]: message })); } validateInput(name) { const validationStatus = this.parseInputValue(name); if (validationStatus.success) return this.setError(name, ''); return this.setError(name, validationStatus.error.issues[0].message); } parseAllInputValues() { const activeErrors = this.inputNames .map((input) => { if (!this.validators[input]) return; this.validateInput(input); }) .filter((err) => err); return activeErrors; } validateForm() { const errors = this.parseAllInputValues(); const isValid = this.checkFormValidity(); if (isValid) return { success: true }; return { success: false, error: errors }; } getInputValue(evt) { const type = evt.target.type; switch (type) { case InputTypes.Text: return evt.target.value; case InputTypes.Checkbox: return evt.target.checked; case InputTypes.Radio: return evt.target.value; default: return evt.target.value; } } // TODO: исправить типы handleInput(evt, name) { const value = this.getInputValue(evt); this.data[name] = value; if (!this.validators[name]) return; this.validateInput(name); this.checkFormValidity(); } handleSelect(name, value, selectField = '') { const data = selectField ? value[selectField] : value; this.data[name] = data; if (!this.validators[name]) return; this.validateInput(name); this.checkFormValidity(); return this.data[name]; } provideInitialValue(elem, name) { return (elem.value = this.data[name]); } defineDynamicField(field) { Object.defineProperty(this.data, field, { get() { return get(this)[field]; }, set(value) { this.update((v) => ({ ...v, [field]: value })); }, configurable: true }); } // TODO: Добавить возможность вписывать кастомные функции registerInput(name, settings = DEFAULT_INPUT_SETTINGS) { this.defineDynamicField(name); this.inputNames.push(name); if (!this.data[name]) this.data[name] = settings.value ?? ''; this.validators[name] = settings.validation || null; if (settings.validation) this.validateInput(name); return { name, value: this.data[name], oninput: (evt) => this.handleInput(evt, name), onmount: (elem) => this.provideInitialValue(elem, name), onselect: (value) => this.handleSelect(name, value, settings?.selectField), errors: this.errors, validators: this.validators }; } registerDataField(name, value) { return (this.data[name] = value); } }