UNPKG

@zeix/ui-element

Version:

UIElement - a HTML-first library for reactive Web Components

65 lines (58 loc) 1.48 kB
import { type Component, asInteger, component, fromEvents, setProperty, setText, show, } from '../../..' export type FormSpinbuttonProps = { value: number } const clickHandler = ({ target, value }) => value + (target.classList.contains('decrement') ? -1 : 1) const keydownHandler = ({ event, value }) => { const { key } = event as KeyboardEvent if (['ArrowUp', 'ArrowDown', '-', '+'].includes(key)) { event.stopPropagation() event.preventDefault() return value + (key === 'ArrowDown' || key === '-' ? -1 : 1) } } export default component( 'form-spinbutton', { value: fromEvents( el => asInteger()(el, el.querySelector('value')?.textContent), 'button', { click: clickHandler, keydown: keydownHandler, }, ), }, (el, { first }) => { const zeroLabel = el.getAttribute('zero-label') || 'Add to Cart' const incrementLabel = el.getAttribute('increment-label') || 'Increment' const max = asInteger(9)(el, el.getAttribute('max')) const nonZero = () => el.value !== 0 return [ first('.value', setText('value'), show(nonZero)), first('.decrement', show(nonZero)), first<HTMLButtonElement>( '.increment', setText(() => (nonZero() ? '+' : zeroLabel)), setProperty('ariaLabel', () => nonZero() ? incrementLabel : zeroLabel, ), setProperty('disabled', () => el.value >= max), ), ] }, ) declare global { interface HTMLElementTagNameMap { 'form-spinbutton': Component<FormSpinbuttonProps> } }