UNPKG

vuestic-ui

Version:
227 lines (226 loc) 6.94 kB
import { ref, computed, watchEffect, toRef, watch, nextTick } from "vue"; import { u as useSyncProp } from "./useSyncProp.mjs"; import { w as watchSetter } from "../utils/watch-setter.mjs"; import { i as isFunction } from "../utils/is-function.mjs"; import { i as isString } from "../utils/is-string.mjs"; import { u as useFormChild } from "./useForm/useFormChild.mjs"; const normalizeValidationRules = (rules = [], callArguments = null) => { if (isString(rules)) { rules = [rules]; } return rules.map((rule) => isFunction(rule) ? rule(callArguments) : rule); }; const useValidationProps = { name: { type: String, default: void 0 }, rules: { type: Array, default: () => [] }, dirty: { type: Boolean, default: false }, error: { type: Boolean, default: void 0 }, errorMessages: { type: [Array, String], default: void 0 }, errorCount: { type: [String, Number], default: 1 }, success: { type: Boolean, default: false }, messages: { type: [Array, String], default: () => [] }, immediateValidation: { type: Boolean, default: false }, modelValue: {} }; const useValidationEmits = ["update:error", "update:errorMessages", "update:dirty"]; const isPromise = (value) => { return typeof value === "object" && typeof value.then === "function"; }; const useDirtyValue = (value, props, emit) => { const isDirty = ref(props.dirty || false); watchSetter(value, () => { isDirty.value = true; emit("update:dirty", true); }); watch(value, (newValue, oldValue) => { if (newValue === oldValue) { isDirty.value = true; } }, { deep: true }); watch(() => props.dirty, (newValue) => { if (isDirty.value === newValue) { return; } isDirty.value = newValue; }); return { isDirty }; }; const useTouched = () => { const isTouched = ref(false); const onBlur = () => { isTouched.value = true; }; return { isTouched, onBlur }; }; const useOncePerTick = (fn) => { let canBeCalled = true; return (...args) => { if (!canBeCalled) { return; } canBeCalled = false; const result = fn(...args); nextTick(() => { canBeCalled = true; }); return result; }; }; const useValidation = (props, emit, options) => { const { reset, focus } = options; const [isError] = useSyncProp("error", props, emit, false); const [errorMessages] = useSyncProp("errorMessages", props, emit, []); const isLoading = ref(false); const { isTouched, onBlur } = useTouched(); const validationAriaAttributes = computed(() => ({ "aria-invalid": isError.value, "aria-errormessage": typeof errorMessages.value === "string" ? errorMessages.value : errorMessages.value.join(", ") })); const resetValidation = () => { errorMessages.value = []; isError.value = false; isDirty.value = false; isTouched.value = false; isLoading.value = false; }; const processResults = (results) => { let error = false; let eMessages = []; results.forEach((result) => { if (isString(result)) { eMessages = [...eMessages, result]; error = true; } else if (result === false) { error = true; } }); errorMessages.value = eMessages; isError.value = error; return !error; }; const validateAsync = async () => { if (!props.rules || !props.rules.length) { return true; } const results = normalizeValidationRules(props.rules.flat(), options.value.value); const asyncPromiseResults = results.filter((result) => isPromise(result)); const syncRules = results.filter((result) => !isPromise(result)); if (!asyncPromiseResults.length) { return processResults(syncRules); } isLoading.value = true; return Promise.all(asyncPromiseResults).then((asyncResults) => { return processResults([...syncRules, ...asyncResults]); }).finally(() => { isLoading.value = false; }); }; const validate = useOncePerTick(() => { if (!props.rules || !props.rules.length) { return true; } const rules = props.rules.flat(); const results = normalizeValidationRules(rules, options.value.value); const asyncPromiseResults = results.filter((result) => isPromise(result)); const syncRules = results.filter((result) => !isPromise(result)); const isSyncedError = syncRules.some((result) => isString(result) ? result : result === false); if (asyncPromiseResults.length && !isSyncedError) { isLoading.value = true; Promise.all(asyncPromiseResults).then((asyncResults) => { processResults([...syncRules, ...asyncResults]); isLoading.value = false; }); return isSyncedError; } return processResults(syncRules); }); watchEffect(() => validate()); const { isDirty } = useDirtyValue(options.value, props, emit); const { // Renamed to forceHideError because it's not clear what it does forceHideErrors, forceHideLoading, forceHideErrorMessages, forceDirty, immediate: isFormImmediate } = useFormChild({ isTouched, isDirty, isValid: computed(() => !isError.value), isLoading, errorMessages, validate, validateAsync, resetValidation, focus, reset: () => { reset(); resetValidation(); validate(); }, value: computed(() => options.value || props.modelValue), name: toRef(props, "name") }); const immediateValidation = computed(() => props.immediateValidation || isFormImmediate.value); let canValidate = true; const withoutValidation = (cb) => { canValidate = false; cb(); nextTick(() => { canValidate = true; }); }; watch(options.value, () => { if (!canValidate) { return; } return validate(); }, { immediate: immediateValidation.value }); return { isDirty, isValid: computed(() => !isError.value), isError, isTouched, isLoading: computed({ get: () => { if (forceHideErrors.value) { return false; } if (immediateValidation.value) { return isLoading.value; } if (isTouched.value || isDirty.value || forceDirty.value) { return isLoading.value; } return false; }, set(value) { isLoading.value = value; } }), computedError: computed(() => { if (forceHideErrors.value) { return false; } if (immediateValidation.value) { return isError.value; } if (isTouched.value || isDirty.value || forceDirty.value) { return isError.value; } return false; }), computedErrorMessages: computed(() => forceHideErrorMessages.value ? [] : errorMessages.value), listeners: { onBlur }, validate, resetValidation, withoutValidation, validationAriaAttributes }; }; export { useValidation as a, useValidationProps as b, useValidationEmits as u }; //# sourceMappingURL=useValidation.mjs.map