vuestic-ui
Version:
Vue 3 UI Framework
227 lines (226 loc) • 6.94 kB
JavaScript
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