UNPKG

@ordojs/forms

Version:

Comprehensive form handling system for OrdoJS

274 lines 8.69 kB
/** * Simplified validation system for forms */ /** * Built-in validation rules */ export class ValidationRules { static required(message = 'This field is required') { return { type: 'required', message, validate: (value) => { if (value === null || value === undefined) return false; if (typeof value === 'string') return value.trim().length > 0; if (typeof value === 'number') return !isNaN(value); if (typeof value === 'boolean') return true; if (value instanceof Date) return !isNaN(value.getTime()); if (value instanceof File) return value.size > 0; return Boolean(value); } }; } static minLength(min, message) { return { type: 'minLength', message: message || `Must be at least ${min} characters`, validate: (value) => { if (value === null || value === undefined) return true; const str = String(value); return str.length >= min; } }; } static maxLength(max, message) { return { type: 'maxLength', message: message || `Must be no more than ${max} characters`, validate: (value) => { if (value === null || value === undefined) return true; const str = String(value); return str.length <= max; } }; } static min(min, message) { return { type: 'min', message: message || `Must be at least ${min}`, validate: (value) => { if (value === null || value === undefined) return true; const num = Number(value); return !isNaN(num) && num >= min; } }; } static max(max, message) { return { type: 'max', message: message || `Must be no more than ${max}`, validate: (value) => { if (value === null || value === undefined) return true; const num = Number(value); return !isNaN(num) && num <= max; } }; } static email(message = 'Must be a valid email address') { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return { type: 'email', message, validate: (value) => { if (value === null || value === undefined || value === '') return true; return emailRegex.test(String(value)); } }; } static url(message = 'Must be a valid URL') { return { type: 'url', message, validate: (value) => { if (value === null || value === undefined || value === '') return true; try { new URL(String(value)); return true; } catch { return false; } } }; } static pattern(regex, message = 'Invalid format') { return { type: 'pattern', message, validate: (value) => { if (value === null || value === undefined || value === '') return true; return regex.test(String(value)); } }; } static oneOf(options, message) { return { type: 'oneOf', message: message || `Must be one of: ${options.join(', ')}`, validate: (value) => { if (value === null || value === undefined) return true; return options.includes(value); } }; } static custom(validator, message = 'Invalid value') { return { type: 'custom', message, validate: validator }; } static equalTo(fieldName, message) { return { type: 'equalTo', message: message || `Must match ${fieldName}`, validate: (value, formValues) => { if (!formValues || value === null || value === undefined) return true; return value === formValues[fieldName]; } }; } static date(message = 'Must be a valid date') { return { type: 'date', message, validate: (value) => { if (value === null || value === undefined || value === '') return true; if (value instanceof Date) return !isNaN(value.getTime()); const date = new Date(String(value)); return !isNaN(date.getTime()); } }; } static file(options = {}) { return { type: 'file', message: options.message || 'Invalid file', validate: (value) => { if (value === null || value === undefined) return true; if (!(value instanceof File)) return false; // Check file size if (options.maxSize && value.size > options.maxSize) { return false; } // Check file type if (options.allowedTypes && !options.allowedTypes.includes(value.type)) { return false; } return true; } }; } } /** * Simple validation manager */ export class ValidationManager { constructor() { this.customValidators = new Map(); } static getInstance() { if (!ValidationManager.instance) { ValidationManager.instance = new ValidationManager(); } return ValidationManager.instance; } /** * Register a custom validator globally */ registerValidator(name, rule) { this.customValidators.set(name, rule); } /** * Get a registered validator */ getValidator(name) { return this.customValidators.get(name); } /** * Validate a single field with multiple rules */ async validateField(value, rules, formValues) { for (const rule of rules) { try { const result = rule.validate(value, formValues); const isValid = result instanceof Promise ? await result : result; if (!isValid) { return { type: rule.type, message: rule.message, field: 'unknown' }; } } catch (error) { return { type: 'validation_error', message: error instanceof Error ? error.message : 'Validation failed', field: 'unknown' }; } } return null; } /** * Combine multiple validation rules */ combineRules(...rules) { return rules; } /** * Create conditional validation rule */ when(condition, thenRule, elseRule) { return { type: 'conditional', message: thenRule.message, validate: (value, formValues) => { if (!formValues) return true; const shouldApplyThenRule = condition(formValues); const ruleToApply = shouldApplyThenRule ? thenRule : elseRule; if (!ruleToApply) return true; return ruleToApply.validate(value, formValues); } }; } } ValidationManager.instance = null; /** * Utility functions for validation */ export const validation = { rules: ValidationRules, manager: ValidationManager.getInstance(), // Common validation patterns email: () => ValidationRules.email(), required: () => ValidationRules.required(), minLength: (min) => ValidationRules.minLength(min), maxLength: (max) => ValidationRules.maxLength(max), pattern: (regex, message) => ValidationRules.pattern(regex, message), // Async validation helper async: (validator, message) => ValidationRules.custom(validator, message) }; //# sourceMappingURL=validation-simple.js.map