@modular-forms/react
Version:
The modular and type-safe form library for React
62 lines (61 loc) • 2.7 kB
JavaScript
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])) }));
}