import type { JSX, ValidComponent } from "@solidjs/web";
import { dynamic } from "@solidjs/web";
import { createEffect, createMemo, omit, untrack } from "solid-js";
import {
type FieldRootState,
useFieldRootContext,
} from "../../internals/field-context.ts";
import { fieldStateAttrs } from "../../internals/field-state-attrs.ts";
import { useAriaLabelledBy } from "../../internals/labelable-provider/use-aria-labelled-by.ts";
import { useLabelableId } from "../../internals/labelable-provider/use-labelable-id.ts";
import { mergeRootProps } from "../../internals/merge-root-props";
import { resolveClassStyle } from "../../internals/resolve-class-style";
import type { BaseUIComponentProps } from "../../internals/types";
import { useFieldControlRegistration } from "../../internals/use-field-control-registration/use-field-control-registration.ts";
import { useFieldMessagesContext } from "../field-messages-context.ts";
export interface FieldControlState extends FieldRootState {}
export interface FieldControlProps
extends BaseUIComponentProps<"input", FieldControlState> {
/** Tag/component to render. Defaults to `"input"`. */
as?: ValidComponent;
}
/**
* The form control to label and validate. Renders an `` element.
*
* Wires:
* - id registration into the surrounding `` (so
* `` can point `htmlFor` at us).
* - value registration into the surrounding `` (so form-level
* validation / submit focus can find us).
* - `aria-labelledby` composed from any labels registered with the provider.
* - `aria-describedby` composed from descriptions + errors registered with
* the field-messages registry.
* - `onInput` / `onBlur` / `onFocus` into the root's touched/dirty/filled/
* focused setters and the validation pipeline (`validation.commit` on
* blur when `validationMode === 'onBlur'`; `validation.getInputValidationProps()`
* merges an `onInput`-driven commit for `onChange`/`onSubmit` modes).
*/
export function FieldControl(props: FieldControlProps): JSX.Element {
const field = useFieldRootContext();
const messages = useFieldMessagesContext();
// Register control id with the labelable-provider so ``'s
// `htmlFor` wires up. `useLabelableId` handles the one-shot registration
// + cleanup. We pass `props.id` (read once, belt-and-braces via
// `untrack` in the hook itself) to honour a consumer override.
const { id } = useLabelableId({
id: untrack(() => (typeof props.id === "string" ? props.id : undefined)),
});
const disabled = createMemo(
(): boolean => field.disabled() || props.disabled === true,
);
const state = createMemo(
(): FieldControlState => ({
...field.state(),
disabled: disabled(),
}),
);
// Register our live value with the surrounding ``. The root
// uses this to key the control into `