import { type ConditionId, getConditionDescription, getConditionsForEdition, } from "@initiative/domain"; import { useLayoutEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; import { useRulesEditionContext } from "../contexts/rules-edition-context.js"; import { useClickOutside } from "../hooks/use-click-outside.js"; import { cn } from "../lib/utils"; import { CONDITION_COLOR_CLASSES, CONDITION_ICON_MAP, } from "./condition-styles.js"; import { Tooltip } from "./ui/tooltip.js"; interface ConditionPickerProps { anchorRef: React.RefObject; activeConditions: readonly ConditionId[] | undefined; onToggle: (conditionId: ConditionId) => void; onClose: () => void; } export function ConditionPicker({ anchorRef, activeConditions, onToggle, onClose, }: Readonly) { const ref = useRef(null); const [pos, setPos] = useState<{ top: number; left: number; maxHeight: number; } | null>(null); useLayoutEffect(() => { const anchor = anchorRef.current; const el = ref.current; if (!anchor || !el) return; const anchorRect = anchor.getBoundingClientRect(); const menuHeight = el.scrollHeight; const pad = 8; const spaceBelow = window.innerHeight - anchorRect.bottom - pad; const spaceAbove = anchorRect.top - pad; const openBelow = spaceBelow >= menuHeight || spaceBelow >= spaceAbove; const top = openBelow ? anchorRect.bottom + 4 : Math.max(pad, anchorRect.top - Math.min(menuHeight, spaceAbove) - 4); const maxHeight = openBelow ? spaceBelow : Math.min(menuHeight, spaceAbove); setPos({ top, left: anchorRect.left, maxHeight }); }, [anchorRef]); useClickOutside(ref, onClose); const { edition } = useRulesEditionContext(); const conditions = getConditionsForEdition(edition); const active = new Set(activeConditions ?? []); return createPortal(
{conditions.map((def) => { const Icon = CONDITION_ICON_MAP[def.iconName]; if (!Icon) return null; const isActive = active.has(def.id); const colorClass = CONDITION_COLOR_CLASSES[def.color] ?? "text-muted-foreground"; return ( ); })}
, document.body, ); }