import { h, type FunctionComponent } from 'preact' import { useCallback, useEffect, useRef, useState } from 'preact/hooks' import cn from 'classnames' import escapeRegex from '../utils/escape_regex.ts' type Styles = { base?: string touched?: string element?: string label?: string statusIcon?: string noMargin?: string icon?: string labelIcon?: string center?: string } & Record & Record & Record type Props = { autoComplete?: string autoFocus?: boolean center?: boolean className?: string classNames?: Partial> color: C defaultValue?: string design: D disabled?: boolean icon: string label: string name: string noMargin?: boolean pattern?: string placeholder?: string required?: boolean sameAs?: string showValidity?: boolean size?: S type?: string value?: any } export default function inputFactory( styles: Styles, ) { const Input: FunctionComponent> = ({ autoComplete, autoFocus, center, className, classNames, color, defaultValue, design, disabled, icon, label, name, noMargin, pattern, placeholder, required, sameAs, size, type = 'text', value, showValidity = true, }) => { const [touched, setTouched] = useState(false) const inputRef = useRef(null) const onBlur = useCallback(() => setTouched(true), []) useEffect(() => { function onInput(e: Event) { inputRef.current!.pattern = escapeRegex((e.target! as HTMLInputElement).value) } const form = inputRef.current!.form! const resetTouched = setTouched.bind(null, false) form.addEventListener('reset', resetTouched) let sameAsInput: HTMLInputElement if (sameAs) { sameAsInput = form[sameAs] sameAsInput.addEventListener('input', onInput) } return () => { form.removeEventListener('reset', resetTouched) if (sameAsInput) sameAsInput.removeEventListener('input', onInput) } }, []) useEffect(() => { if (autoFocus) inputRef.current!.focus() }, [autoFocus]) const id = styles.element + '_' + name return (
{icon && (styles.icon || classNames?.icon) && (
)} {showValidity && } {/** *