import { dynamic } from "@solidjs/web";
import { createMemo, omit, untrack } from "solid-js";
import { useBaseUiId } from "../../internals/base-ui-id.jsx";
import { createChangeEventDetails, REASONS } from "../../internals/change-event-details.jsx";
import { composeRefs, userRef } from "../../internals/compose-refs.jsx";
import { ACTIVE_COMPOSITE_ITEM } from "../../internals/composite/composite-constants.jsx";
import { useCompositeListItem } from "../../internals/composite/composite-list.jsx";
import { useFieldRootContext } from "../../internals/field-context.jsx";
import { fieldStateAttrs } from "../../internals/field-state-attrs.jsx";
import { HiddenInput } from "../../internals/hidden-input/hidden-input.jsx";
import { useAriaLabelledBy } from "../../internals/labelable-provider/use-aria-labelled-by.jsx";
import { readOption } from "../../internals/maybe-accessor.jsx";
import { mergeRootProps } from "../../internals/merge-root-props.jsx";
import { resolveClassStyle } from "../../internals/resolve-class-style.jsx";
import { ariaLabelledBy as seedAriaLabelledBy } from "../../internals/seed-aria-attr.jsx";
import { serializeValue } from "../../internals/serialize-value.jsx";
import { useButton } from "../../internals/use-button/use-button.jsx";
import { useFieldControlValidation } from "../../internals/use-field-control-validation/use-field-control-validation.jsx";
import { useValueChanged } from "../../internals/use-value-changed.jsx";
import { useRadioGroupContext } from "../../radio-group/radio-group-context.jsx";
import { createRadio } from "../create-radio.jsx";
import { RadioRootContext } from "../radio-root-context.jsx";
/**
 * A selectable input in a group of options. Renders a non-native
 * `<button role="radio">` (default tag) or `as` override, plus a hidden
 * `<input type="radio">` beside it for native form submission.
 *
 * Solid 2.0-native rewire (§1 wave 1): replaces `renderElement` with
 * `dynamic(() => props.as ?? "button")` and threads
 * `createRadio().trigger()` (carrying role=radio, aria-checked/readonly/
 * required, data-checked/unchecked/disabled/readonly/required, onClick)
 * through `mergeRootProps` together with useButton + field-validation +
 * field-state attrs + the group-aware onFocus handler.
 */
export function RadioRoot(props) {
  const field = useFieldRootContext();
  const group = useRadioGroupContext();
  const disabled = () => field.disabled() || group.disabled() || props.disabled === true;
  const readOnly = () => group.readOnly() || readOption(props.readOnly) === true;
  const required = () => group.required() || readOption(props.required) === true;
  const nativeButton = () => props.nativeButton ?? true;
  const inGroup = () => group.present;
  const controlledChecked = () => {
    if (inGroup()) {
      return group.checkedValue() === props.value;
    }
    return Boolean(readOption(props.checked));
  };
  const c = createRadio({
    checked: controlledChecked,
    disabled,
    readOnly,
    required,
    onCheckedChange: (next, event) => {
      const details = createChangeEventDetails(REASONS.none, event);
      if (inGroup()) {
        group.setCheckedValue(props.value, details);
        props.onCheckedChange?.(next, details);
        if (details.isCanceled) event.preventDefault();
        return;
      }
      props.onCheckedChange?.(next, details);
      if (details.isCanceled) event.preventDefault();
    }
  });
  const checked = c.checked;
  const {
    props: buttonProps,
    ref: buttonRef
  } = useButton({
    disabled,
    native: nativeButton
  });
  const {
    ref: compositeItemRef
  } = useCompositeListItem({});
  const id = useBaseUiId();
  const controlRef = {
    current: null
  };
  const validation = useFieldControlValidation({
    value: checked,
    id: () => id,
    controlRef,
    getValue: () => validation.inputRef.current?.checked ?? checked(),
    enabled: () => !group.present
  });
  const {
    getAriaInvalidProps,
    inputRef: fieldInputRef
  } = validation;
  useValueChanged(checked, () => {
    const value = checked();
    field.setFilled(value);
    field.setDirty(value !== field.validityData().initialValue);
    if (field.shouldValidateOnChange()) {
      void validation.commit(value);
    } else {
      void validation.commit(value, true);
    }
  });
  const serializedValue = createMemo(() => serializeValue(props.value));
  const state = () => ({
    ...field.state(),
    checked: checked(),
    disabled: disabled(),
    readOnly: readOnly(),
    required: required()
  });
  const contextValue = {
    state,
    checked
  };
  const ariaLabelledBy = useAriaLabelledBy(() => {
    const v = props["aria-labelledby"];
    return typeof v === "string" ? v : undefined;
  });

  // Field-state attrs (data-valid/invalid/touched/dirty/filled/focused)
  // not carried by c.trigger(). Spreading `fieldStateAttrs(...)` directly
  // would invoke its getters at body time and trip
  // `[STRICT_READ_UNTRACKED]`; combine via `mergeRootProps` so each
  // getter stays lazy.
  const radioExtraAttrs = {
    get id() {
      return id;
    }
  };
  const radioStateAttrs = mergeRootProps(radioExtraAttrs, fieldStateAttrs(state));

  // Group-aware onFocus: arrow-key navigation that lands on a radio when
  // `group.touched()` is set should auto-select. The primitive's onClick
  // handles click selection; we just add onFocus here.
  const focusHandler = {
    onFocus: event => {
      if (event.defaultPrevented) return;
      if (disabled() || readOnly()) return;
      if (!group.present || !group.touched()) return;
      group.setTouched(false);
      if (checked()) return;
      const details = createChangeEventDetails(REASONS.none, event);
      group.setCheckedValue(props.value, details);
    }
  };
  const userStyling = resolveClassStyle(props, () => state());
  const userProps = omit(props, "class", "style", "attrs", "as", "aria-labelledby", "checked", "children", "disabled", "inputRef", "name", "nativeButton", "onCheckedChange", "readOnly", "required", "value");

  // Compose: useButton ∘ aria-labelledby ∘ field-validation aria-invalid ∘
  // c.trigger() ∘ fieldStateAttrs ∘ focusHandler ∘ userProps. Event
  // handlers chain in declaration order, gated by defaultPrevented.
  const styledUserProps = mergeRootProps(userStyling, userProps);
  let merged = mergeRootProps(buttonProps, seedAriaLabelledBy(ariaLabelledBy));
  merged = mergeRootProps(merged, getAriaInvalidProps());
  merged = mergeRootProps(merged, c.trigger());
  merged = mergeRootProps(merged, radioStateAttrs);
  merged = mergeRootProps(merged, focusHandler);
  merged = mergeRootProps(merged, styledUserProps);
  const Tag = dynamic(() => props.as ?? "button");
  const buttonElement = <Tag {...merged} ref={composeRefs(el => untrack(() => {
    controlRef.current = el;
    if (el && group.present && checked()) {
      el.setAttribute(ACTIVE_COMPOSITE_ITEM, "");
    }
  }), buttonRef, compositeItemRef, userRef(props))}>
			<RadioRootContext value={contextValue}>{props.children}</RadioRootContext>
		</Tag>;
  const hiddenInput = <HiddenInput type="radio" aria-hidden="true" tabindex={-1} ref={el => {
    fieldInputRef.current = el;
    props.inputRef?.(el);
  }} name={group.name() ?? field.name() ?? props.name} value={serializedValue()} checked={checked()} disabled={disabled()} required={required()} />;
  return <>
			{buttonElement}
			{hiddenInput}
		</>;
}
//# sourceMappingURL=radio-root.jsx.map
