UNPKG

@modular-forms/react

Version:

The modular and type-safe form library for React

62 lines (61 loc) 2.7 kB
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime"; import { effect } from '@preact/signals-react'; import { useMemo, } from 'react'; import { useLifecycle, useLiveSignal } from '../hooks'; import { getElementInput, handleFieldEvent, initializeFieldStore, } from '../utils'; /** * Headless form field that provides reactive properties and state. */ export function Field({ children, type, ...props }) { // Destructure props const { of: form, name } = props; // Get store of specified field const field = useMemo(() => initializeFieldStore(form, name), [form, name]); // Use lifecycle of field useLifecycle({ ...props, store: field }); // Create readonly live signals // https://github.com/preactjs/signals/issues/361 const value = useLiveSignal(field.value); const error = useLiveSignal(field.error); const active = useLiveSignal(field.active); const touched = useLiveSignal(field.touched); const dirty = useLiveSignal(field.dirty); return (_jsx(_Fragment, { children: children(useMemo(() => ({ name, value, error, active, touched, dirty, }), // eslint-disable-next-line react-hooks/exhaustive-deps [name]), useMemo(() => ({ name, ref(element) { if (element) { // Add element to elements field.elements.value = [...field.elements.value, element]; // Create effect that replaces initial input and input of field with // initial input of element if both is "undefined", so that dirty // state also resets to "false" when user removes input effect(() => { if (element.type !== 'radio' && field.startValue.value === undefined && field.value.peek() === undefined) { setTimeout(() => { const input = getElementInput(element, field, type); field.startValue.value = input; field.value.value = input; }); } }); } }, onChange(event) { handleFieldEvent(form, field, name, event, ['touched', 'change'], getElementInput(event.currentTarget, field, type)); }, onBlur(event) { handleFieldEvent(form, field, name, event, ['touched', 'blur']); }, }), [field, form, name, type])) })); }