@stackoverfloweth/vue-compositions
Version:
A collection of reusable vue compositions.
121 lines • 3.64 kB
JavaScript
import { computed, onMounted, onUnmounted, reactive, ref, watch, unref, toRef } from 'vue';
import { isValidationAbortedError } from '../useValidation/ValidationAbortedError';
import { ValidationRuleExecutor } from '../useValidation/ValidationExecutor';
import { VALIDATION_OBSERVER_INJECTION_KEY } from '../useValidationObserver/useValidationObserver';
import { asArray } from '../utilities/arrays';
import { injectFromSelfOrAncestor } from '../utilities/injection';
import { isSame } from '../utilities/isSame';
function isRules(value) {
return typeof unref(value) !== 'string';
}
export function useValidation(value, nameOrRules, maybeRules) {
if (isRules(nameOrRules)) {
return useValidation(value, 'Value', nameOrRules);
}
if (maybeRules === undefined) {
throw new Error('Invalid useValidation arguments');
}
const valueRef = toRef(value);
const nameRef = ref(nameOrRules);
const rulesRef = computed(() => asArray(unref(maybeRules)));
const previousValueRef = ref();
const error = ref('');
const valid = computed(() => error.value === '');
const invalid = computed(() => !valid.value);
const pending = ref(false);
const validated = ref(false);
const executor = new ValidationRuleExecutor();
const validate = async ({ source } = {}) => {
executor.abort();
pending.value = true;
try {
const result = await executor.validate({
source,
value: valueRef.value,
name: nameRef.value,
rules: rulesRef.value,
previousValue: previousValueRef.value,
});
error.value = result;
pending.value = false;
validated.value = true;
previousValueRef.value = valueRef.value;
}
catch (error) {
if (!isValidationAbortedError(error)) {
console.warn('There was an error during validation');
console.error(error);
}
}
return valid.value;
};
const reset = (resetCallback) => {
error.value = '';
pending.value = false;
validated.value = false;
if (resetCallback) {
pause();
try {
resetCallback();
}
finally {
resume();
}
}
};
const pause = () => {
stopWatch?.();
stopWatch = undefined;
};
const resume = () => {
if (stopWatch) {
return;
}
startWatcher();
};
const state = reactive({
valid,
invalid,
error,
pending,
validated,
});
const validation = {
valid,
invalid,
error,
pending,
validated,
validate,
reset,
pause,
resume,
state,
};
let mounted = false;
let stopWatch;
function startWatcher() {
stopWatch = watch(valueRef, (newValue, oldValue) => {
if (!mounted) {
return;
}
if (isSame(newValue, oldValue)) {
return;
}
validate({ source: 'validator' });
}, { deep: true });
}
startWatcher();
const observer = injectFromSelfOrAncestor(VALIDATION_OBSERVER_INJECTION_KEY);
let unregister;
onMounted(() => {
unregister = observer?.register(validation);
mounted = true;
});
onUnmounted(() => {
stopWatch?.();
unregister?.();
});
return validation;
}
//# sourceMappingURL=useValidation.js.map