import type { JSX, ValidComponent } from "@solidjs/web"; import { dynamic } from "@solidjs/web"; import { omit } 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 SwitchRootState, useSwitchRootContext, } from "../switch-root-context.ts"; export interface SwitchThumbState extends SwitchRootState {} export interface SwitchThumbProps extends BaseUIComponentProps<"span", SwitchThumbState> { /** * Tag/component to render. Defaults to `"span"`. Replaces the * pre-spike `render` prop (axis G). */ as?: ValidComponent; } /** * The movable part of the switch that indicates whether the switch is on or * off. Renders a `` element (or `as` override). * * 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. */ export function SwitchThumb(props: SwitchThumbProps): JSX.Element { const context = useSwitchRootContext(); const state = context.state; 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"); const styledUserProps = mergeRootProps(userStyling, userProps); const merged = mergeRootProps(stateAttrs, styledUserProps); const Tag = dynamic(() => props.as ?? "span"); return ; }