{"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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"}