{"version":3,"file":"validator-BOzNBRh6.js","sources":["../src/scripts/components/form/validation/domUtils.js","../src/scripts/components/form/validation/rules.js","../src/scripts/components/form/validation/uiManager.js","../src/scripts/components/form/validation/validator.js"],"sourcesContent":["export const domUtils = {\n findFieldWrapper: (el) => {\n if (!el) return null;\n const selectors = [\".form-field-wrapper\", \".form-field\", \".field\"];\n const element = el.length ? el[0] : el;\n return element.closest ? selectors.map((s) => element.closest(s)).find(Boolean) : null;\n },\n\n shouldValidateField: (field) => {\n const wrapper = domUtils.findFieldWrapper(field);\n if (wrapper && wrapper.offsetHeight === 0) return false;\n if (field.closest(\"fieldset[disabled]\")) return false;\n if (field.getAttribute(\"aria-required\") === \"true\") return true;\n if (field.getAttribute(\"data-required\") === \"true\") return true;\n if (!field.name || field.disabled || field.readonly) return false;\n\n return true;\n },\n};\n","import { domUtils } from \"./domUtils\";\n\nexport const validators = {\n required: (value, element) => ({\n isValid: element.type === \"checkbox\" ? element.checked : value != null && value.toString().trim().length > 0,\n defaultMessage: \"Required\",\n }),\n\n email: (value, element) => ({\n isValid: !value || element?.checkValidity?.() !== false,\n defaultMessage: \"Invalid email address\",\n }),\n\n minLength: (value, element, min) => ({\n isValid: !value || (element?.checkValidity?.() !== false && value.length >= min),\n defaultMessage: `Must be at least ${min} characters`,\n }),\n\n maxLength: (value, element, max) => ({\n isValid: !value || (element?.checkValidity?.() !== false && value.length <= max),\n defaultMessage: `Must not exceed ${max} characters`,\n }),\n\n pattern: (value, element, pattern) => ({\n isValid: !value || (element?.checkValidity?.() !== false && pattern.test(value)),\n defaultMessage: \"Please match the requested format\",\n }),\n\n min: (value, element, min) => ({\n isValid: !value || (element?.checkValidity?.() !== false && Number(value) >= min),\n defaultMessage: `Must be at least ${min}`,\n }),\n\n max: (value, element, max) => ({\n isValid: !value || (element?.checkValidity?.() !== false && Number(value) <= max),\n defaultMessage: `Must not exceed ${max}`,\n }),\n\n checkboxset: (_, element) => {\n const parent = element.closest(\".checkboxset\");\n const checked = parent.querySelectorAll(\"input:checked\").length;\n\n return {\n isValid: checked > 0,\n defaultMessage: \"Please select one\",\n };\n },\n};\n\nexport const buildRules = (form) => {\n const rules = {};\n\n form.querySelectorAll(\"input:not([type=hidden]), textarea, select\").forEach((field) => {\n if (!domUtils.shouldValidateField(field)) return;\n\n const fieldRules = [];\n\n if (field.required) fieldRules.push({ type: \"required\" });\n if (field.type === \"email\") fieldRules.push({ type: \"email\" });\n if (field.minLength > 0) fieldRules.push({ type: \"minLength\", min: field.minLength });\n if (field.maxLength > 0) fieldRules.push({ type: \"maxLength\", max: field.maxLength });\n if (field.min) fieldRules.push({ type: \"min\", min: Number(field.min) });\n if (field.max) fieldRules.push({ type: \"max\", max: Number(field.max) });\n if (field.pattern) fieldRules.push({ type: \"pattern\", pattern: new RegExp(field.pattern) });\n\n if (fieldRules.length) {\n rules[field.name] = fieldRules;\n }\n });\n\n form.querySelectorAll(\"[aria-required], [data-required]\").forEach((field) => {\n if (!domUtils.shouldValidateField(field)) return;\n\n const fieldRules = [];\n\n if (field.classList.contains(\"optionset\") && !field.classList.contains(\"checkboxset\")) {\n const radio = field.querySelector(\"input[type=radio]\");\n\n if (radio) {\n fieldRules.push({ type: \"required\" });\n rules[radio.name] = fieldRules;\n }\n }\n\n if (field.classList.contains(\"checkboxset\")) {\n const checkbox = field.querySelector(\"input[type=checkbox]\");\n\n if (checkbox) {\n fieldRules.push({ type: \"checkboxset\" });\n rules[checkbox.name] = fieldRules;\n }\n }\n\n if (field.classList.contains(\"checkbox\")) {\n fieldRules.push({ type: \"required\" });\n rules[field.name] = fieldRules;\n }\n });\n\n return rules;\n};\n\nexport const validateRule = (value, element) => (rule) => {\n const { type, message, ...options } = rule;\n\n const validator = validators[type];\n if (!validator) return { isValid: true };\n\n const param = options.min || options.max || options.pattern;\n const result = validator(value, element, param);\n\n return {\n isValid: result.isValid,\n message: message || result.defaultMessage,\n };\n};\n","import { domUtils } from \"./domUtils\";\n\nexport const uiManager = {\n addFieldError: (field, message) => {\n if (!field || !message) return;\n\n // Clear any existing error first\n uiManager.removeFieldError(field);\n\n const errorContainer = document.createElement(\"div\");\n errorContainer.className = \"form-field-message bad\";\n errorContainer.textContent = message;\n\n const wrapper = domUtils.findFieldWrapper(field);\n\n if (wrapper) {\n wrapper.appendChild(errorContainer);\n wrapper.classList.add(\"has-error\");\n }\n\n if (field.length === undefined) {\n field.classList.add(\"has-error\");\n }\n\n uiManager.setupErrorClearingListeners(field);\n },\n\n removeFieldError: (field) => {\n const wrapper = domUtils.findFieldWrapper(field);\n\n if (!wrapper) {\n return;\n }\n\n const errorContainer = wrapper.querySelector(\".form-field-message\");\n\n if (errorContainer) {\n errorContainer.remove();\n wrapper.removeEventListener(\"change\", wrapper.errorClearHandler);\n delete wrapper.errorClearHandler;\n\n wrapper.classList.remove(\"has-error\");\n\n if (field.length === undefined) {\n field.classList.remove(\"has-error\");\n }\n }\n },\n\n setupErrorClearingListeners: (field) => {\n const wrapper = domUtils.findFieldWrapper(field);\n\n if (!wrapper) {\n return;\n }\n\n if (wrapper.errorClearHandler) {\n wrapper.removeEventListener(\"change\", wrapper.errorClearHandler);\n }\n\n wrapper.errorClearHandler = () => uiManager.removeFieldError(field);\n wrapper.addEventListener(\"change\", wrapper.errorClearHandler, { once: true });\n },\n\n updateFormUI: (form, errors) => {\n uiManager.clearFormErrors(form);\n\n Object.entries(errors).forEach(([fieldName, fieldErrors]) => {\n const field = form.elements[fieldName];\n if (!field || !fieldErrors.length) return;\n\n const errorContainer = document.createElement(\"div\");\n errorContainer.className = \"form-field-message bad\";\n errorContainer.textContent = fieldErrors[0];\n\n const wrapper = domUtils.findFieldWrapper(field);\n\n if (wrapper) {\n wrapper.appendChild(errorContainer);\n wrapper.classList.add(\"has-error\");\n }\n\n if (field.length === undefined) {\n field.classList.add(\"has-error\");\n }\n\n uiManager.setupErrorClearingListeners(field);\n });\n },\n\n clearFormErrors: (form) => {\n form.querySelectorAll(\"input, select, textarea\").forEach(uiManager.removeFieldError);\n },\n};\n","import { validators, validateRule, buildRules } from \"./rules\";\nimport { uiManager } from \"./uiManager\";\n\nexport const validationCore = {\n validateField: (value, element, rules) => {\n return rules\n .map(validateRule(value, element))\n .filter((result) => !result.isValid)\n .map((result) => result.message);\n },\n\n validateData: (rules) => (data) => {\n const errors = Object.entries(rules).reduce((acc, [fieldName, fieldRules]) => {\n const fieldData = data[fieldName];\n const value = fieldData?.value ?? fieldData;\n const element = fieldData?.element;\n const fieldErrors = validationCore.validateField(value, element, fieldRules);\n\n return fieldErrors.length ? { ...acc, [fieldName]: fieldErrors } : acc;\n }, {});\n\n return {\n isValid: Object.keys(errors).length === 0,\n errors,\n };\n },\n};\n\nexport const createValidator = (form) => ({\n validateForm: () => {\n const rules = buildRules(form);\n const formData = Object.entries(rules).reduce(\n (acc, [fieldName]) => ({\n ...acc,\n [fieldName]: {\n value: form.elements[fieldName]?.value,\n element: form.elements[fieldName],\n },\n }),\n {},\n );\n\n const result = validationCore.validateData(rules)(formData);\n uiManager.updateFormUI(form, result.errors);\n return result;\n },\n\n validateField: (fieldName) => {\n const rules = buildRules(form);\n const element = form.elements[fieldName];\n\n if (!element || !rules[fieldName]) {\n return { isValid: true, errors: {} };\n }\n\n const result = validationCore.validateData({ [fieldName]: rules[fieldName] })({\n [fieldName]: { value: element.value, element },\n });\n\n uiManager.updateFormUI(form, result.errors);\n return result;\n },\n\n addValidator: (name, validatorFn, defaultMessage) => {\n validators[name] = (value, element, ...params) => ({\n isValid: validatorFn(value, element, ...params),\n defaultMessage,\n });\n },\n\n addFieldError: (field, message) => uiManager.addFieldError(field, message),\n\n clearErrors: () => uiManager.clearFormErrors(form),\n});\n"],"names":["domUtils","el","selectors","element","s","field","wrapper","validators","value","_a","min","max","pattern","_","buildRules","form","rules","fieldRules","radio","checkbox","validateRule","rule","type","message","options","validator","param","result","uiManager","errorContainer","errors","fieldName","fieldErrors","validationCore","data","acc","fieldData","createValidator","formData","name","validatorFn","defaultMessage","params"],"mappings":"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"}