/** * PXM Number Input Component * * Enhanced number input with increment/decrement controls and validation. * This component provides structure and behavior only - all styling is controlled by your CSS. * * Features: * - Increment/decrement buttons with automatic min/max bounds * - Built-in validation with customizable error messages * - Keyboard navigation support * - Dynamic content support (buttons can be added/removed after initialization) * - Event-driven system for custom handling * - Respects native input attributes (min, max, step, value, disabled) * * Keyboard Navigation: * - ArrowUp - Increment value * - ArrowDown - Decrement value * - Enter - Validate current value * - Standard input navigation (Tab, etc.) * * Basic Usage: * * * * *
*
* * Dynamic Content: * const numberInput = document.querySelector('pxm-number-input'); * const newButton = document.createElement('button'); * newButton.setAttribute('data-plus', ''); * numberInput.appendChild(newButton); // Automatically initialized * * With Custom Validation: * const numberInput = document.querySelector('pxm-number-input'); * numberInput.setCustomValidator((value) => { * if (value % 5 !== 0) return 'Value must be divisible by 5'; * return null; // Valid * }); * * Consumer Styling: * Use CSS to style pxm-number-input, its input, buttons, and [data-error] elements. * The component only manages functional states like disabled attributes and display/opacity for errors. * * Events: * - pxm:number-input:change - Fired when value changes (user input or programmatic) * - pxm:number-input:increment - Fired when value is incremented * - pxm:number-input:decrement - Fired when value is decremented * - pxm:number-input:error - Fired when validation error occurs * - pxm:number-input:valid - Fired when validation passes * - pxm:number-input:buttons-changed - Fired when buttons are dynamically added/removed * * Accessibility: * This component manages only essential ARIA attributes (like aria-invalid for functionality). * Additional ARIA attributes, labels, and roles should be added by the consumer as needed. */ export interface NumberInputEventDetail { value: number; previousValue?: number; input: HTMLInputElement; } export interface NumberInputErrorEventDetail { message: string; type: 'min' | 'max' | 'step' | 'invalid' | 'custom'; value: number; } export interface NumberInputValidEventDetail { value: number; input: HTMLInputElement; } declare class PxmNumberInput extends HTMLElement { private config; private state; private _input; private _minusButtons; private _plusButtons; private _errorElement; private mutationObserver?; private customValidator?; private initializedButtons; private buttonEventListeners; private get input(); private get minusButtons(); private get plusButtons(); private get errorElement(); static get observedAttributes(): string[]; constructor(); connectedCallback(): void; disconnectedCallback(): void; attributeChangedCallback(name: string, oldValue: string, newValue: string): void; /** * Set up MutationObserver to watch for dynamically added/removed buttons */ private observeChildChanges; /** * Check if an element is a number input button */ private isButton; /** * Handle dynamic changes to buttons */ private handleDynamicChanges; /** * Clean up event listeners for buttons that have been removed */ private cleanupRemovedButtons; /** * Set up the number input component */ private setupNumberInput; /** * Sync internal state from input value */ private syncStateFromInput; /** * Ensure error element exists */ private ensureErrorElement; /** * Set up input event listeners */ private setupInputListeners; /** * Handle keyboard navigation */ private handleKeydown; /** * Set up button event listeners */ private setupButtons; /** * Add an event listener to a button and track it for cleanup */ private addButtonEventListener; /** * Clean up all event listeners for all buttons */ private cleanupAllEventListeners; /** * Handle input value changes */ private onInputChange; /** * Update button disabled states based on current value and constraints */ private updateButtonStates; /** * Show error message */ private showError; /** * Hide error message */ private hideError; /** * Get error message for a validation type */ private getErrorMessage; /** * Increment the value by the step amount */ increment(): void; /** * Decrement the value by the step amount */ decrement(): void; /** * Set the input value programmatically */ setValue(value: number): void; /** * Get the current input value */ getValue(): number; /** * Focus the input element */ focus(): void; /** * Blur the input element */ blur(): void; /** * Validate the current value against constraints */ validate(): boolean; /** * Set a custom validation function */ setCustomValidator(validator: (value: number) => string | null): void; /** * Clear the custom validation function */ clearCustomValidator(): void; /** * Get the current validation state */ isValid(): boolean; /** * Check if there are any validation errors */ hasError(): boolean; } export type { PxmNumberInput };