import type { JSX } from "@solidjs/web"; import { createMemo } from "solid-js"; import { type FieldValidityData, type FieldValidityState as FieldValidityStateRaw, getCombinedFieldValidityData, useFieldRootContext, } from "../../internals/field-context.ts"; /** * Snapshot passed to ``'s function child. Mirrors React's * `FieldValidity.State` shape — the `state` slot (inside * `FieldValidityData`) is re-exposed as `validity` for API clarity. */ export interface FieldValidityState extends Omit { /** The raw validity state (`ValidityState`-shaped). */ validity: FieldValidityStateRaw; } export interface FieldValidityProps { /** * Function child that receives the current validity snapshot. Must be a * function — `` exists specifically to expose the snapshot * for consumer-rendered UI. * * ```tsx * * {(validity) => validity.validity.valueMissing * ? Required * : null} * * ``` */ children: (state: FieldValidityState) => JSX.Element; } /** * Renders nothing by itself — passes the current validity snapshot to its * function child. Mirrors Base UI React's ``. * * Solid 2 note: the snapshot is recomputed inside a `createMemo` so the * function child re-evaluates only when the validity or external `invalid` * flag actually changes. */ export function FieldValidity(props: FieldValidityProps): JSX.Element { const field = useFieldRootContext(); const snapshot = createMemo((): FieldValidityState => { const combined = getCombinedFieldValidityData( field.validityData(), field.invalid(), ); return { validity: combined.state, errors: combined.errors, error: combined.error, value: combined.value, initialValue: combined.initialValue, }; }); // Return a JSX expression that re-invokes the child as `snapshot()` // updates — Solid's compiler tracks this as a reactive dependency. return <>{props.children(snapshot())}; }