UNPKG

neumorphic-peripheral

Version:

A lightweight, framework-agnostic JavaScript/TypeScript library for beautiful neumorphic styling

218 lines (217 loc) 8.21 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.InputComponent = void 0; exports.input = input; const base_1 = require("./base"); const utils_1 = require("../utils"); const validators_1 = require("../validators"); class InputComponent extends base_1.BaseComponent { constructor(element, config = {}) { if (!(element instanceof HTMLInputElement)) { throw new Error('Input component requires an HTMLInputElement'); } super(element, config); this._validationResult = null; this._inputConfig = { validateOn: 'blur', showValidation: true, ...config }; this._debouncedValidate = (0, utils_1.debounce)(() => this.performValidation(), 300); } get inputElement() { return this._element; } init() { this.applyBaseStyles(); this.applyInputStyles(); this.setupValidation(); } bindEvents() { super.bindEvents(); // Focus events this.addEventListener(this._element, 'focus', this.handleFocus.bind(this)); this.addEventListener(this._element, 'blur', this.handleBlur.bind(this)); // Input validation events if (this._inputConfig.validateOn === 'change') { this.addEventListener(this._element, 'input', this._debouncedValidate); } else if (this._inputConfig.validateOn === 'blur') { this.addEventListener(this._element, 'blur', () => this.performValidation()); } // Custom input event this.addEventListener(this._element, 'input', () => { this.emit('input', { value: this.getValue() }); }); } applyInputStyles() { (0, utils_1.addClassName)(this._element, 'input'); // Core input styles this._element.style.boxShadow = this.createShadowStyle('inset'); this._element.style.padding = '12px 16px'; this._element.style.fontSize = '16px'; this._element.style.lineHeight = '1.5'; this._element.style.width = this._element.style.width || '100%'; this._element.style.boxSizing = 'border-box'; // Placeholder styling this.applyPlaceholderStyles(); // Set up hover and focus effects this.setupInteractionEffects(); } applyPlaceholderStyles() { if (this._inputConfig.placeholder) { this.inputElement.placeholder = this._inputConfig.placeholder; } // Create placeholder color CSS if it doesn't exist const placeholderColor = `color: ${this._theme.colors.textSecondary}; opacity: 1;`; const styleId = 'np-placeholder-styles'; if (!document.getElementById(styleId)) { const style = document.createElement('style'); style.id = styleId; style.textContent = ` .np-input::placeholder { ${placeholderColor} } .np-input::-webkit-input-placeholder { ${placeholderColor} } .np-input::-moz-placeholder { ${placeholderColor} } .np-input:-ms-input-placeholder { ${placeholderColor} } `; document.head.appendChild(style); } } setupInteractionEffects() { const originalShadow = this.createShadowStyle('inset'); const focusShadow = `${this.createShadowStyle('inset')}, 0 0 0 2px ${this._theme.colors.accent}40`; this.addEventListener(this._element, 'mouseenter', () => { if (!this._config.disabled && !this.inputElement.matches(':focus')) { this._element.style.boxShadow = this.createHoverShadowStyle('inset'); } }); this.addEventListener(this._element, 'mouseleave', () => { if (!this.inputElement.matches(':focus')) { this._element.style.boxShadow = originalShadow; } }); } handleFocus() { (0, utils_1.addClassName)(this._element, 'focused'); this._element.style.boxShadow = `${this.createShadowStyle('inset')}, 0 0 0 2px ${this._theme.colors.accent}40`; this.emit('focus'); } handleBlur() { this._element.classList.remove('np-focused'); this._element.style.boxShadow = this.createShadowStyle('inset'); this.emit('blur'); } setupValidation() { if (!this._inputConfig.validate) return; // Set up ARIA attributes for accessibility this._element.setAttribute('aria-invalid', 'false'); if (this._inputConfig.errorMessage) { const errorId = `error-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; this._element.setAttribute('aria-describedby', errorId); } } performValidation() { if (!this._inputConfig.validate || !this._inputConfig.showValidation) return; const value = this.getValue(); this._validationResult = (0, validators_1.validateValue)(value, this._inputConfig.validate); // Update global validation manager validators_1.globalValidationManager.validate(this._element, this._inputConfig.validate); // Update visual state this.updateValidationState(); // Emit validation event this.emit('validation', { result: this._validationResult, value }); return this._validationResult; } updateValidationState() { if (!this._validationResult) return; // Update ARIA attributes this._element.setAttribute('aria-invalid', this._validationResult.isValid ? 'false' : 'true'); if (this._validationResult.isValid) { this._element.classList.remove('np-error'); this._element.style.boxShadow = this.createShadowStyle('inset'); } else { (0, utils_1.addClassName)(this._element, 'error'); this._element.style.boxShadow = `${this.createShadowStyle('inset')}, 0 0 0 2px ${this._theme.colors.error}40`; } } // Public API methods validate() { return this.performValidation() || { isValid: true, errors: [] }; } getValue() { return (0, utils_1.getElementValue)(this._element); } setValue(value) { (0, utils_1.setElementValue)(this._element, value); this.emit('input', { value }); // Trigger validation if configured if (this._inputConfig.validateOn === 'change') { this._debouncedValidate(); } } clearErrors() { this._validationResult = null; validators_1.globalValidationManager.clearValidation(this._element); this._element.classList.remove('np-error'); this._element.setAttribute('aria-invalid', 'false'); this._element.style.boxShadow = this.createShadowStyle('inset'); } focus() { this.inputElement.focus(); } blur() { this.inputElement.blur(); } select() { this.inputElement.select(); } isValid() { return this._validationResult ? this._validationResult.isValid : true; } getValidationResult() { return this._validationResult; } onUpdate(newConfig) { const oldConfig = { ...this._inputConfig }; this._inputConfig = { ...this._inputConfig, ...newConfig }; // Update placeholder if (newConfig.placeholder !== oldConfig.placeholder) { this.applyPlaceholderStyles(); } // Update validation configuration if (newConfig.validate !== oldConfig.validate) { this.clearErrors(); if (newConfig.validate) { this.setupValidation(); } } // Update validation timing if (newConfig.validateOn !== oldConfig.validateOn) { // Re-bind validation events this.bindEvents(); } } onDestroy() { validators_1.globalValidationManager.clearValidation(this._element); } } exports.InputComponent = InputComponent; // Factory function for easy usage function input(element, config = {}) { return new InputComponent(element, config); }