import type { JSX, ValidComponent } from "@solidjs/web"; import { dynamic } from "@solidjs/web"; import { omit, Show } from "solid-js"; import { mergeRootProps } from "../../internals/merge-root-props"; import { resolveClassStyle } from "../../internals/resolve-class-style"; import type { BaseUIComponentProps } from "../../internals/types"; import { type RadioRootState, useRadioRootContext, } from "../radio-root-context.ts"; export interface RadioIndicatorState extends RadioRootState {} export interface RadioIndicatorProps extends BaseUIComponentProps<"span", RadioIndicatorState> { /** * Tag/component to render. Defaults to `"span"`. Replaces the * pre-spike `render` prop (axis G). */ as?: ValidComponent; /** * Whether to keep the element mounted in the DOM when the radio is not * checked. * @default false */ keepMounted?: boolean | undefined; } /** * Indicates whether the radio button is selected. Renders a `` (or * `as` override) inside ``. * * Solid 2.0-native rewire (ยง1 wave 1): replaces `renderElement` with * `dynamic(() => props.as ?? "span")` and emits the same `data-*` * projection (`data-checked`/`data-unchecked` plus the field-state * attrs) inline as getters reading from the root context's state * accessor. The `` gate is preserved. */ export function RadioIndicator(props: RadioIndicatorProps): JSX.Element { const context = useRadioRootContext(); const state = context.state; const shouldRender = (): boolean => { if (props.keepMounted === true) return true; return context.checked(); }; const stateAttrs = { get "data-checked"(): "" | undefined { return state().checked ? "" : undefined; }, get "data-unchecked"(): "" | undefined { return state().checked ? undefined : ""; }, get "data-disabled"(): "" | undefined { return state().disabled ? "" : undefined; }, get "data-readonly"(): "" | undefined { return state().readOnly ? "" : undefined; }, get "data-required"(): "" | undefined { return state().required ? "" : undefined; }, get "data-valid"(): "" | undefined { return state().valid === true ? "" : undefined; }, get "data-invalid"(): "" | undefined { return state().valid === false ? "" : undefined; }, get "data-touched"(): "" | undefined { return state().touched ? "" : undefined; }, get "data-dirty"(): "" | undefined { return state().dirty ? "" : undefined; }, get "data-filled"(): "" | undefined { return state().filled ? "" : undefined; }, get "data-focused"(): "" | undefined { return state().focused ? "" : undefined; }, }; const userStyling = resolveClassStyle(props, () => state()); const userProps = omit(props, "class", "style", "attrs", "as", "keepMounted"); const styledUserProps = mergeRootProps(userStyling, userProps); const merged = mergeRootProps(stateAttrs, styledUserProps); const Tag = dynamic(() => props.as ?? "span"); return ( ); }