import type { JSX, ValidComponent } from "@solidjs/web";
/**
* `
` — visual indicator shown inside a checked
* ``. Mirrors React.
*/
import { dynamic } from "@solidjs/web";
import { createMemo, omit, Show } from "solid-js";
import { composeRefs, userRef } from "../../internals/compose-refs";
import type { MutableRef } from "../../internals/floating-ui/types";
import { mergeRootProps } from "../../internals/merge-root-props";
import { useOpenChangeComplete } from "../../internals/popups/use-open-change-complete";
import { resolveClassStyle } from "../../internals/resolve-class-style";
import type { BaseUIComponentProps } from "../../internals/types";
import {
type TransitionStatus,
useTransitionStatus,
} from "../../internals/use-transition-status/use-transition-status";
import { useMenuCheckboxItemContext } from "../checkbox-item/menu-checkbox-item-context";
export interface MenuCheckboxItemIndicatorState {
checked: boolean;
disabled: boolean;
highlighted: boolean;
transitionStatus: TransitionStatus;
}
export interface MenuCheckboxItemIndicatorProps
extends BaseUIComponentProps<"span", MenuCheckboxItemIndicatorState> {
/**
* Tag/component to render. Defaults to `"span"`. Replaces the
* pre-spike `render` prop (axis G).
*/
as?: ValidComponent;
/** @default false */
keepMounted?: boolean | undefined;
}
export function MenuCheckboxItemIndicator(
props: MenuCheckboxItemIndicatorProps,
): JSX.Element {
const item = useMenuCheckboxItemContext();
const indicatorRef: MutableRef = { current: null };
const setRef = (el: HTMLElement | null): void => {
indicatorRef.current = el;
};
const { mounted, transitionStatus, setMounted } = useTransitionStatus(
item.checked,
);
useOpenChangeComplete({
open: item.checked,
ref: indicatorRef,
onComplete: () => {
if (!item.checked()) setMounted(false);
},
});
const keepMounted = (): boolean => props.keepMounted ?? false;
const shouldRender = (): boolean => keepMounted() || mounted();
const state = createMemo(() => ({
checked: item.checked(),
disabled: item.disabled(),
highlighted: item.highlighted(),
transitionStatus: transitionStatus(),
}));
const internal = {
"aria-hidden": true,
get "data-highlighted"() {
return state().highlighted ? "" : undefined;
},
get "data-disabled"() {
return state().disabled ? "" : undefined;
},
get "data-checked"() {
return state().checked ? "" : undefined;
},
get "data-unchecked"() {
return state().checked ? undefined : "";
},
get "data-starting-style"() {
return state().transitionStatus === "starting" ? "" : undefined;
},
get "data-ending-style"() {
return state().transitionStatus === "ending" ? "" : undefined;
},
};
const userClassStyle = resolveClassStyle(props, () => state());
const userProps = omit(
props,
"as",
"class",
"style",
"attrs",
"keepMounted",
);
let merged: Record = mergeRootProps(
internal,
userClassStyle,
);
merged = mergeRootProps(merged, userProps);
const Tag = dynamic(() => props.as ?? "span");
return (
);
}