import type { JSX, ValidComponent } from "@solidjs/web"; 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 { useSelectItemContext } from "../item/select-item-context"; export interface SelectItemIndicatorState { selected: boolean; transitionStatus: TransitionStatus; } export interface SelectItemIndicatorProps extends BaseUIComponentProps<"span", SelectItemIndicatorState> { as?: ValidComponent; keepMounted?: boolean | undefined; } /** * `` — a `` that renders when the enclosing * `` is selected. */ export function SelectItemIndicator( props: SelectItemIndicatorProps, ): JSX.Element { const item = useSelectItemContext(); const keepMounted = (): boolean => props.keepMounted ?? false; const shouldRender = (): boolean => keepMounted() || item.selected(); return {}; } function Inner(props: SelectItemIndicatorProps): JSX.Element { const item = useSelectItemContext(); const indicatorRef: MutableRef = { current: null }; const { mounted, transitionStatus, setMounted } = useTransitionStatus( item.selected, ); useOpenChangeComplete({ open: item.selected, ref: indicatorRef, onComplete: () => { if (!item.selected()) setMounted(false); }, }); const state = createMemo(() => ({ selected: item.selected(), transitionStatus: transitionStatus(), })); const setRef = (el: HTMLElement | null): void => { indicatorRef.current = el; }; const internal = { "aria-hidden": "true" as const, children: "✔️" as JSX.Element, 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 ( ); }