UNPKG

@gleb.askerko/componentkit-js

Version:

Lightweight, framework-agnostic JavaScript component library with progress gift components

243 lines (201 loc) 5.79 kB
export class Input { constructor(options = {}) { this.options = { type: 'text', placeholder: '', label: '', value: '', required: false, disabled: false, validation: {}, className: '', onChange: null, onBlur: null, onFocus: null, ...options }; this.element = null; this.labelElement = null; this.errorElement = null; this.container = null; this.wrapper = null; this.isValid = true; } render(selector) { this.container = typeof selector === 'string' ? document.querySelector(selector) : selector; if (!this.container) { throw new Error(`Container not found: ${selector}`); } this.wrapper = this.createWrapper(); this.container.appendChild(this.wrapper); this.bindEvents(); return this; } createWrapper() { const wrapper = document.createElement('div'); wrapper.className = 'ck-input-wrapper'; if (this.options.label) { this.labelElement = this.createLabel(); wrapper.appendChild(this.labelElement); } this.element = this.createInput(); wrapper.appendChild(this.element); this.errorElement = this.createErrorElement(); wrapper.appendChild(this.errorElement); return wrapper; } createLabel() { const label = document.createElement('label'); label.className = 'ck-input-label'; label.textContent = this.options.label; return label; } createInput() { const input = document.createElement('input'); input.type = this.options.type; input.placeholder = this.options.placeholder; input.value = this.options.value; input.required = this.options.required; input.disabled = this.options.disabled; input.className = this.getInputClasses(); return input; } createErrorElement() { const error = document.createElement('div'); error.className = 'ck-input-error'; error.style.display = 'none'; return error; } getInputClasses() { const baseClasses = 'ck-input'; const stateClasses = { error: 'ck-input--error', disabled: 'ck-input--disabled' }; return [ baseClasses, !this.isValid ? stateClasses.error : '', this.options.disabled ? stateClasses.disabled : '', this.options.className ].filter(Boolean).join(' '); } bindEvents() { if (!this.element) return; this.element.addEventListener('input', (e) => { this.validate(e.target.value); if (this.options.onChange) { this.options.onChange(e); } }); this.element.addEventListener('blur', (e) => { this.validate(e.target.value); if (this.options.onBlur) { this.options.onBlur(e); } }); this.element.addEventListener('focus', (e) => { if (this.options.onFocus) { this.options.onFocus(e); } }); } validate(value) { const errors = []; // Required validation if (this.options.required && !value.trim()) { errors.push('This field is required'); } // Email validation if (this.options.validation.email && value) { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(value)) { errors.push('Please enter a valid email address'); } } // Min length validation if (this.options.validation.minLength && value.length < this.options.validation.minLength) { errors.push(`Minimum ${this.options.validation.minLength} characters required`); } // Max length validation if (this.options.validation.maxLength && value.length > this.options.validation.maxLength) { errors.push(`Maximum ${this.options.validation.maxLength} characters allowed`); } // Pattern validation if (this.options.validation.pattern && value) { const pattern = new RegExp(this.options.validation.pattern); if (!pattern.test(value)) { errors.push(this.options.validation.patternMessage || 'Invalid format'); } } this.isValid = errors.length === 0; this.showErrors(errors); this.updateClasses(); return this.isValid; } showErrors(errors) { if (errors.length > 0) { this.errorElement.textContent = errors[0]; this.errorElement.style.display = 'block'; } else { this.errorElement.style.display = 'none'; } } updateClasses() { if (this.element) { this.element.className = this.getInputClasses(); } } update(newOptions) { this.options = { ...this.options, ...newOptions }; if (this.element) { this.element.type = this.options.type; this.element.placeholder = this.options.placeholder; this.element.value = this.options.value; this.element.required = this.options.required; this.element.disabled = this.options.disabled; this.updateClasses(); } if (this.labelElement && this.options.label) { this.labelElement.textContent = this.options.label; } return this; } getValue() { return this.element ? this.element.value : this.options.value; } setValue(value) { this.options.value = value; if (this.element) { this.element.value = value; this.validate(value); } return this; } focus() { if (this.element) { this.element.focus(); } return this; } blur() { if (this.element) { this.element.blur(); } return this; } clear() { return this.setValue(''); } destroy() { if (this.wrapper && this.wrapper.parentNode) { this.wrapper.parentNode.removeChild(this.wrapper); } this.element = null; this.labelElement = null; this.errorElement = null; this.wrapper = null; this.container = null; } }