import { CheckIcon } from "lucide-react";
import {
createContext,
useContext,
useEffect,
useMemo,
type ReactNode,
type RefObject,
} from "react";
import { DropdownMenuRadioGroup, DropdownMenuRadioItem } from "../../../ui/dropdown-menu";
import {
MENU_BUTTON_CLASS,
MENU_CHECK_CLASS,
MENU_CHECK_SLOT_CLASS,
MENU_META_CLASS,
} from "../../../ui/menu-styles";
import { cn } from "../../lib/utils";
/** Dropdowns rove through menu items; dialogs use ordinary Tab stops. */
export type MenuBodyPresentation = "menu" | "dialog";
const RadioGroupContext = createContext<{
presentation: MenuBodyPresentation;
value: string | null;
}>({ presentation: "menu", value: null });
export function RadioGroup(props: {
presentation: MenuBodyPresentation;
label: string;
value: string | null;
className?: string | undefined;
children: ReactNode;
}) {
const { presentation, value } = props;
const context = useMemo(() => ({ presentation, value }), [presentation, value]);
return (
{presentation === "menu" ? (
{props.children}
) : (
{props.children}
)}
);
}
export function RadioRow(props: {
value: string;
disabled?: boolean | undefined;
icon?: ReactNode | undefined;
label: string;
meta?: string | undefined;
className?: string | undefined;
ref?: ((node: HTMLElement | null) => void) | undefined;
onSelect: () => void;
}) {
const group = useContext(RadioGroupContext);
const content = (
<>
{props.icon}
{props.label}
{props.meta ? {props.meta} : null}
>
);
if (group.presentation === "menu") {
return (
{
// Choices can reveal more choices, or report a pending mutation.
event.preventDefault();
props.onSelect();
}}
className={cn("cursor-pointer", props.className)}
>
{content}
);
}
const checked = group.value === props.value;
return (
);
}
/** A drill-in replaces its opener; start roving focus on the checked enabled row. */
export function useFocusCheckedRow(
ref: RefObject,
presentation: MenuBodyPresentation,
) {
useEffect(() => {
const body = ref.current;
if (presentation !== "menu" || !body || body.contains(document.activeElement)) return;
const enabled = '[role="menuitemradio"]:not([data-disabled])';
const row =
body.querySelector(`${enabled}[aria-checked="true"]`) ??
body.querySelector(enabled);
row?.focus({ preventScroll: true });
// Only on open: later choices keep focus where the user put it.
}, [ref, presentation]);
}