UNPKG

@sparkstone/solid-validation

Version:

A lightweight form validation library for Solid.js with PocketBase integration.

1 lines 11.4 kB
{"version":3,"file":"main.cjs","sources":["../src/main.ts"],"sourcesContent":["import { createSignal } from 'solid-js';\nimport { createStore, SetStoreFunction } from 'solid-js/store';\n\ntype Falsy = false | 0 | '' | null | undefined | void;\ntype MaybePromise<T> = T | Promise<T>;\n\ntype ValidatorResponse = MaybePromise<string | Falsy>;\n\nexport type Validator<Element> = Falsy | ((el: Element) => ValidatorResponse);\n\ntype ValidatedElement = HTMLElement & { name: string };\n\ntype OnFormSubmit<ErrorFields extends Object, Payload> = (\n el: Payload,\n) => MaybePromise<void | Partial<ErrorFields>>;\n\ndeclare module 'solid-js' {\n namespace JSX {\n interface Directives {\n formSubmit: (callback: HTMLFormElement) => any;\n validate: boolean | Validator<any>[];\n }\n }\n}\nfunction checkValid<ErrorFields extends Object>(\n { element, validators = [] }: { element: HTMLInputElement; validators: Validator<unknown>[] },\n setErrors: SetStoreFunction<Partial<ErrorFields>>,\n errorClass?: string,\n) {\n return async () => {\n element.setCustomValidity?.('');\n element.checkValidity?.();\n\n let message = element.validationMessage;\n if (!message) {\n for (const validator of validators) {\n if (!validator) continue;\n const text = await validator(element);\n if (text) {\n message = text;\n element.setCustomValidity?.(text);\n break;\n }\n }\n }\n if (message) {\n errorClass && element.classList.toggle(errorClass, true);\n element.setAttribute('aria-invalid', 'true');\n setErrors({\n [element.name ?? element.dataset.name]: message,\n } as Partial<ErrorFields>);\n }\n return message;\n };\n}\n\nexport function useForm<ErrorFields extends Object>({ errorClass = '' } = {}) {\n const [errors, setErrors] = createStore<Partial<ErrorFields>>({});\n const [isSubmitting, setIsSubmitting] = createSignal(false);\n const [isSubmitted, setIsSubmitted] = createSignal(false);\n const fields: Partial<Record<keyof ErrorFields, { element: HTMLInputElement; validators: any }>> =\n {};\n\n const validate = <Element extends ValidatedElement>(\n ref: Element,\n accessor: () => Falsy | Validator<Element>[] = () => {},\n ) => {\n queueMicrotask(() => {\n let name = ref.name ?? ref.dataset.name;\n const accessorValue = accessor();\n const validators = Array.isArray(accessorValue) ? accessorValue : [];\n let config;\n fields[name] = config = { element: ref, validators };\n ref.onblur = () => {\n setIsSubmitted(false);\n return checkValid(config, setErrors, errorClass);\n };\n ref.oninput = () => {\n setIsSubmitted(false);\n if (!errors[name]) return;\n setErrors({ [name]: undefined } as Partial<ErrorFields>);\n ref.setAttribute('aria-invalid', 'false');\n errorClass && ref.classList.toggle(errorClass, false);\n };\n });\n };\n\n /**\n * Validate a field based on name\n * returns true if the field is valid\n **/\n async function validateField(fieldName: keyof ErrorFields): Promise<boolean> {\n const field = fields[fieldName];\n if (!field) return false;\n let error = await checkValid(field, setErrors, errorClass)();\n if (field.element.validationMessage || error) {\n field.element.focus();\n field.element.scrollIntoView({ behavior: 'smooth' });\n }\n return !errors[fieldName];\n }\n\n function getFieldValue(fieldName: keyof ErrorFields) {\n const field = fields[fieldName];\n return field?.element.value;\n }\n\n async function submit<Payload>(callback: OnFormSubmit<ErrorFields, Payload>, ref?: Payload) {\n let errored = false;\n\n for (const k in fields) {\n const field = fields[k];\n if (!field) continue;\n let error = await checkValid(field, setErrors, errorClass)();\n if (!errored && (field.element.validationMessage || error)) {\n field.element.focus();\n field.element.scrollIntoView({ behavior: 'smooth' });\n if (document.contains(field.element)) {\n errored = true;\n } else {\n delete fields[k];\n }\n }\n }\n if (errored) return;\n setIsSubmitting(true);\n let callbackResult = await callback(ref);\n if (callbackResult instanceof Object) {\n for (const name in callbackResult) {\n if (!(name in fields)) continue;\n fields[name]!.element.setAttribute('aria-invalid', 'true');\n }\n setErrors(callbackResult);\n } else {\n clearErrors();\n setIsSubmitted(true);\n }\n setIsSubmitting(false);\n }\n\n function clearErrors() {\n setErrors(\n errors =>\n Object.fromEntries(\n Object.entries(errors).map(([key, value]) => [key, undefined]),\n ) as Partial<ErrorFields>,\n );\n }\n\n const formSubmit = (\n ref: HTMLFormElement,\n accessor: () => OnFormSubmit<ErrorFields, HTMLFormElement>,\n ) => {\n const callback = accessor() || (() => {});\n setIsSubmitted(false);\n\n ref.setAttribute('novalidate', '');\n\n ref.onsubmit = async e => {\n e.preventDefault();\n\n await submit(callback, ref);\n };\n\n ref.onreset = () => {\n clearErrors();\n };\n };\n\n return {\n validate,\n formSubmit,\n submit,\n errors,\n isSubmitting,\n isSubmitted,\n validateField,\n getFieldValue,\n validateRef:\n <Element extends ValidatedElement>(...args: Validator<Element>[]) =>\n (ref: Element) =>\n validate(ref, () => args),\n };\n}\n"],"names":["_settle","pact","state","value","s","_Pact","bind","v","then","observer","o","prototype","onFulfilled","onRejected","result","this","callback","e","_this","_isSettledPact","thenable","array","body","check","reject","_cycle","i","length","checkValid","_ref","setErrors","errorClass","element","_ref$validators","validators","_temp3","_element$name","_setErrors","message","classList","toggle","setAttribute","name","dataset","setCustomValidity","checkValidity","validationMessage","_temp2","_interrupt","_temp","_forOf","validator","Promise","resolve","text","_temp4","submit","ref","_temp6","errored","setIsSubmitting","callbackResult","Object","fields","clearErrors","setIsSubmitted","_temp5","k","field","error","focus","scrollIntoView","behavior","document","contains","_forIn","_ref2$errorClass","_createStore","createStore","errors","_createSignal","createSignal","isSubmitting","_createSignal2","validate","accessor","queueMicrotask","_ref$name","config","accessorValue","Array","isArray","onblur","oninput","_setErrors2","undefined","fromEntries","entries","map","_ref3","formSubmit","onsubmit","preventDefault","onreset","isSubmitted","validateField","fieldName","getFieldValue","validateRef","_arguments","arguments","slice","call"],"mappings":"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"}