@gleb.askerko/componentkit-js
Version:
Lightweight, framework-agnostic JavaScript component library with progress gift components
243 lines (201 loc) • 5.79 kB
JavaScript
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;
}
}