UNPKG

maz-ui

Version:

A standalone components library for Vue.Js 3 & Nuxt.Js 3

1 lines 9.34 kB
import{useFreezeValue}from"../composables/useFreezeValue.js";import{getCurrentInstance,inject,nextTick}from"vue";import{isEqual}from"@maz-ui/utils/helpers/isEqual";import{debounceId}from"@maz-ui/utils/helpers/debounceId";import{throttleId}from"@maz-ui/utils/helpers/throttleId";var CONFIG={mode:`lazy`,scrollToErrorSelector:`.has-field-error`,debounceTime:300,throttleTime:1e3};function isEmptyValue(value){return value==null||value===``}var storeValidbot={};async function getValibotValidationMethod(methodName){if(storeValidbot[methodName])return storeValidbot[methodName];let valibot=await import(`valibot`);return storeValidbot[methodName]=valibot[methodName],valibot[methodName]}async function getValidationSchema(formSchema){return(await getValibotValidationMethod(`objectAsync`))(formSchema)}async function getFieldValidationResult(name,schema,value){let fieldSchema=await getValidationSchema(schema);let result=await(await getValibotValidationMethod(`safeParseAsync`))(fieldSchema.entries[name],value??``);return{result,isValid:result.success}}async function setFieldValidationState({name,fieldState,schema,payload,setError=!0,setErrorIfInvalidAndNotEmpty=!1}){if(await nextTick(),fieldState.validating)return Promise.resolve();fieldState.validating=!0;try{if(!schema[name]){fieldState.valid=!0,fieldState.validating=!1,fieldState.validated=!0,fieldState.errors=[],fieldState.error=!1;return}let{result,isValid}=await getFieldValidationResult(name,schema,payload[name]);fieldState.valid=isValid;let shouldSetError=setError||setErrorIfInvalidAndNotEmpty&&!isValid&&!isEmptyValue(payload[name]);let shouldPreserveError=fieldState.blurred&&!isValid&&fieldState.mode&&[`eager`,`blur`,`progressive`].includes(fieldState.mode);(shouldSetError||shouldPreserveError)&&(fieldState.error=!isValid),fieldState.errors=result.issues??[],fieldState.validated=!0}finally{fieldState.validating=!1}}function validateForm({fieldsStates,payload,setErrors=!0,schema}){return Promise.all(Object.keys(fieldsStates).map(name=>setFieldValidationState({name,setError:setErrors,fieldState:fieldsStates[name],payload,schema,setErrorIfInvalidAndNotEmpty:fieldsStates[name].mode===`lazy`})))}function getErrorMessages(errors,fieldsStates){let errorMessages={};for(let[name,value]of Object.entries(errors)){let issues=value;errorMessages[name]=fieldsStates[name].error&&issues[0]?issues[0].message:void 0}return errorMessages}function getFieldsErrors(fieldsStates){let fieldsErrors={};for(let[name,fieldState]of Object.entries(fieldsStates))fieldsErrors[name]=fieldState.errors;return fieldsErrors}function getValidateFunction({name,hasValidation,debouncedFields,throttledFields}){if(!hasValidation)return;let fieldName=String(name);if(debouncedFields?.[fieldName]&&throttledFields?.[fieldName])throw Error(`The field "${String(fieldName)}" cannot be both debounced and throttled`);return debouncedFields?.[fieldName]?debounceId(String(fieldName),setFieldValidationState,typeof debouncedFields[fieldName]==`number`?debouncedFields[fieldName]:CONFIG.debounceTime):throttledFields?.[fieldName]?throttleId(String(fieldName),setFieldValidationState,typeof throttledFields[fieldName]==`number`?throttledFields[fieldName]:CONFIG.throttleTime):setFieldValidationState}function getFieldState({name,schema,initialValue,fieldState,options}){let hasValidation=schema?fieldHasValidation(name,schema):!1;let validateFunction=getValidateFunction({name,hasValidation,debouncedFields:options?.debouncedFields,throttledFields:options?.throttledFields});return{blurred:!1,dirty:!1,errors:[],error:!1,valid:!hasValidation,validating:!1,validated:!1,initialValue:useFreezeValue(initialValue),validateFunction,mode:hasValidation?options?.mode??fieldState?.mode??CONFIG.mode:void 0}}function fieldHasValidation(field,schema){return Object.keys(schema).includes(field)}function getFieldsStates({schema,payload,options}){let fieldsStates={};for(let fieldName in schema){let name=fieldName;fieldsStates[name]=getFieldState({name,schema,options,fieldState:fieldsStates[name],initialValue:payload?.[name]})}return fieldsStates}function updateFieldsStates({fieldsStates,payload,schema,options,updateMode=!1}){for(let fieldName in schema){let name=fieldName;fieldsStates[name]=updateFieldState({name,fieldState:fieldsStates[name],payload,schema,options,updateMode})}}function updateFieldState({name,fieldState,payload,schema,options,updateMode=!0}){let{initialValue,mode,...rest}=getFieldState({name,schema,initialValue:options.defaultValue??payload[name],fieldState,options});let newMode=updateMode?mode??fieldState.mode??CONFIG.mode:fieldState.mode;return{...fieldState,initialValue,mode:newMode,...fieldState?.mode&&newMode!==fieldState.mode?rest:{}}}function canExecuteValidation({eventName,fieldState,isSubmitted}){let{dirty,blurred,mode,valid}=fieldState;return eventName===`blur`&&(hasModeIncludes([`lazy`,`aggressive`],mode)||valid)||eventName===`input`&&mode===`blur`||!mode?!1:isSubmitted||mode===`eager`&&blurred||mode===`blur`&&blurred||mode===`aggressive`&&dirty||mode===`lazy`&&dirty||mode===`progressive`}function handleFieldBlur({name,force=!1,payload,fieldState,schema,isSubmitted}){let fieldValue=payload[name];let isDirty=!isEqual(fieldValue,fieldState.initialValue);if(fieldState.dirty=isDirty,fieldState.blurred=fieldState.blurred||(fieldState.mode===`eager`?isDirty:!0),force||canExecuteValidation({eventName:`blur`,fieldState,isSubmitted}))return fieldState.validateFunction?.({name,fieldState,schema,payload,setError:fieldState.mode===`progressive`?fieldState.validated||fieldState.blurred:!0})}function handleFieldInput({name,payload,fieldState,schema,isSubmitted,forceValidation=!1}){let fieldValue=payload[name];if(fieldState.validated=!1,fieldState.dirty=!isEqual(fieldValue,fieldState.initialValue),forceValidation||canExecuteValidation({eventName:`input`,fieldState,isSubmitted}))return fieldState.validateFunction?.({name,fieldState,schema,payload,setError:fieldState.mode===`progressive`?fieldState.validated||fieldState.blurred:!0})}function hasModeIncludes(modes,value){return value?modes.includes(value):!1}function getInstance(composableName){let instance=getCurrentInstance();if(!instance)throw Error(`${composableName} must be called within setup()`);return instance}function getContext(identifier,composableName){let context=getInstance(composableName).formContexts?.get(identifier)??inject(identifier);if(!context)throw Error(`useFormField must be used within a form (useFormValidator)`);return context}function scrollToError(selector=CONFIG.scrollToErrorSelector){let element=document.querySelector(selector);element&&element.scrollIntoView({behavior:`smooth`,block:`center`})}function findInteractiveElements(el){if(isInteractiveElement(el))return[el];let selector=[`input`,`select`,`textarea`,`button`,`a[href]`,`[tabindex]:not([tabindex="-1"])`,`[role="button"]`,`[role="textbox"]`,`[role="combobox"]`,`[role="listbox"]`,`[role="slider"]`,`[role="spinbutton"]`,`[role="switch"]`,`[role="checkbox"]`,`[role="radio"]`,`[role="menuitem"]`,`[role="option"]`,`[contenteditable="true"]`,`[data-interactive]`,`.interactive`,`[data-clickable]`].join(`, `);return[...el.querySelectorAll(selector)].filter(isInteractiveElement)}function isInteractiveElement(el){if(el.getAttribute(`tabindex`)===`-1`)return!1;if(el instanceof HTMLInputElement||el instanceof HTMLSelectElement||el instanceof HTMLTextAreaElement||el instanceof HTMLButtonElement||el instanceof HTMLAnchorElement&&el.href||el.hasAttribute(`tabindex`)&&el.getAttribute(`tabindex`)!==`-1`)return!0;let interactiveRoles=[`button`,`textbox`,`combobox`,`listbox`,`slider`,`spinbutton`,`switch`,`checkbox`,`radio`,`menuitem`,`option`];let role=el.getAttribute(`role`);return role&&interactiveRoles.includes(role)||el.getAttribute(`contenteditable`)===`true`?!0:el.hasAttribute(`data-interactive`)||el.hasAttribute(`data-clickable`)||el.classList.contains(`interactive`)}var activeListeners=new WeakMap;function addEventToInteractiveElements({interactiveElements,onBlur,mode}){interactiveElements.forEach(element=>{if(hasModeIncludes([`eager`,`blur`,`progressive`],mode)){let existingListeners=activeListeners.get(element);existingListeners?.has(`blur`)&&element.removeEventListener(`blur`,existingListeners.get(`blur`)),element.addEventListener(`blur`,onBlur),activeListeners.has(element)||activeListeners.set(element,new Map),activeListeners.get(element).set(`blur`,onBlur)}})}function removeEventFromInteractiveElements({interactiveElements,onBlur}){interactiveElements.forEach(element=>{let existingListeners=activeListeners.get(element);existingListeners?.has(`blur`)&&(element.removeEventListener(`blur`,onBlur),existingListeners.delete(`blur`),existingListeners.size===0&&activeListeners.delete(element))})}function getValidationEvents({hasRef,fieldState,onBlur}){if(!(hasRef||hasModeIncludes([`aggressive`,`lazy`],fieldState.mode)))return{onBlur}}export{setFieldValidationState as _,scrollToError as a,getFieldsStates as c,handleFieldInput as d,hasModeIncludes as f,getFieldsErrors as g,getErrorMessages as h,removeEventFromInteractiveElements as i,getInstance as l,updateFieldsStates as m,findInteractiveElements as n,fieldHasValidation as o,updateFieldState as p,getValidationEvents as r,getContext as s,addEventToInteractiveElements as t,handleFieldBlur as u,validateForm as v,CONFIG as y};