UNPKG

@stackoverfloweth/vue-compositions

Version:

A collection of reusable vue compositions.

121 lines 3.64 kB
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