UNPKG

@inkline/inkline

Version:

Inkline is the intuitive UI Components library that gives you a developer-friendly foundation for building high-quality, accessible, and customizable Vue.js 3 Design Systems.

129 lines (128 loc) 4.18 kB
import { clone, getValueByPath, setValueByPath, setValuesAlongPath } from "@grozav/utils"; import { computed, inject, ref, unref, watch } from "vue"; import { FormKey, FormGroupKey } from "@inkline/inkline/constants"; import { setSchemaStateRecursively, validateSchema } from "@inkline/inkline/validation"; import { useInkline } from "@inkline/inkline/composables/useInkline"; export function useValidation(options) { const inkline = useInkline(); const form = inject(FormKey, null); const formGroup = inject(FormGroupKey, null); const schema = form ? computed( () => form.schema && options.validate?.value && getValueByPath(form.schema.value, options.name.value) ) : ref(options.schema?.value || null); if (!form && options.schema?.value) { watch( () => options.schema?.value, (value) => { schema.value = value; } ); } function shouldValidate(schema2, eventName) { if (!options.validate?.value) { return; } const events = schema2.validateOn ? [].concat(schema2.validateOn) : inkline?.options?.validateOn; return events.includes(eventName); } async function setValue(name, value) { if (!options.validate?.value) { return; } let resolvedSchema = clone(schema.value); const targetSchema = getValueByPath(resolvedSchema, name); if (!targetSchema) { throw new Error( 'Schema to be validated not found. Did you forget to match the schema key to the input "name" prop?' ); } resolvedSchema = setValueByPath(resolvedSchema, `${name}.value`, value); resolvedSchema = setValuesAlongPath(resolvedSchema, name, { pristine: false, dirty: true }); if (shouldValidate(targetSchema, "input")) { resolvedSchema = await validateSchema(resolvedSchema); } schema.value = resolvedSchema; options.onUpdate?.(resolvedSchema); } async function setTouched(name, event) { if (!options.validate?.value) { return; } let resolvedSchema = clone(schema.value); const targetSchema = getValueByPath(resolvedSchema, name); if (!targetSchema) { throw new Error( 'Schema to be validated not found. Did you forget to match the schema key to the input "name" prop?' ); } resolvedSchema = setValuesAlongPath(resolvedSchema, name, { untouched: false, touched: true }); if (shouldValidate(targetSchema, event.type)) { resolvedSchema = await validateSchema(resolvedSchema); } schema.value = resolvedSchema; options.onUpdate?.(resolvedSchema); } async function onSubmit(event) { if (!options.validate?.value) { return; } let resolvedSchema = await validateSchema(schema.value); resolvedSchema = setSchemaStateRecursively(resolvedSchema, { untouched: false, touched: true }); if (resolvedSchema.valid) { options.onSubmit?.(event); } schema.value = resolvedSchema; options.onUpdate?.(resolvedSchema); } async function onInput(nameRef, value) { const name = unref(nameRef); if (!options.validate?.value || !name) { return; } if (formGroup) { formGroup.onInput(name, value); } else if (form) { form.onInput(name, value); } else if (options.schema?.value) { await setValue(name, value); } } function onBlur(nameRef, event) { const name = unref(nameRef); if (!options.validate?.value || !name) { return; } if (formGroup) { formGroup.onBlur(name, event); } else if (form) { form.onBlur(name, event); } else if (options.schema?.value) { setTouched(name, event); } } return { schema, onSubmit, onInput, onBlur }; } export function useFormValidationError(options) { const hasError = computed(() => { if (typeof options.error.value === "boolean") { return options.error.value; } else if (options.schema.value && options.error.value) { let visible = true; [].concat(options.error.value).forEach((status) => { visible = visible && options.schema.value[status]; }); return visible; } return false; }); return { hasError }; }