import clsx from "clsx"; import { Check } from "lucide-react"; import * as React from "react"; import { useTranslation } from "react-i18next"; import { Divider } from "~/components/Divider"; import { ModeImage } from "~/components/Image"; import { shortStageName, stageIds } from "~/modules/in-game-lists/stage-ids"; import type { ModeShort, StageId } from "~/modules/in-game-lists/types"; import { nullFilledArray } from "~/utils/arrays"; import { stageImageUrl } from "~/utils/urls"; import styles from "./ModeMapPoolPicker.module.css"; export function ModeMapPoolPicker({ mode, amountToPick, pool, allowedStages, unavailableLabel, onChange, modeTabs, onModeChange, disabled, }: { mode: ModeShort; amountToPick: number; pool: StageId[]; /** Stages that can be picked. The rest are shown greyed out with `unavailableLabel`, or not at all without one. */ allowedStages: readonly StageId[]; unavailableLabel?: string; onChange: (stages: StageId[]) => void; /** When provided, the divider becomes a tab switcher between these modes. */ modeTabs?: ModeShort[]; onModeChange?: (mode: ModeShort) => void; disabled?: boolean; }) { const [wigglingStageId, setWigglingStageId] = React.useState( null, ); const stages: (StageId | null)[] = [ ...pool, ...nullFilledArray(amountToPick - pool.length), ]; const handlePickedStageClick = (stageId: StageId) => { onChange(pool.filter((s) => s !== stageId)); }; const handleUnpickedStageClick = (stageId: StageId) => { if (stages[amountToPick - 1] !== null) { setWigglingStageId(stageId); return; } if (pool.includes(stageId)) { return; } onChange([...pool, stageId].sort((a, b) => a - b)); }; return (
{nullFilledArray(amountToPick).map((_, index) => { return ( ); })}
{modeTabs && onModeChange ? (
{modeTabs.map((tabMode) => { const active = tabMode === mode; return ( ); })}
) : ( )}
{stageIds.map((stageId) => { const unavailable = !allowedStages.includes(stageId); if (unavailable && !unavailableLabel) return null; const selected = stages.includes(stageId); const onClick = () => { if (disabled) return; if (unavailable) return; if (selected) return handlePickedStageClick(stageId); handleUnpickedStageClick(stageId); }; return ( setWigglingStageId(null)} disabled={disabled} testId={`map-pool-${mode}-${stageId}`} /> ); })}
); } function MapSlot({ number, picked }: { number: number; picked: boolean }) { return (
{picked ? : number}
); } function MapButton({ stageId, onClick, selected, unavailable, unavailableLabel, wiggle, onWiggleEnd, disabled, testId, }: { stageId: StageId; onClick: () => void; selected?: boolean; unavailable?: boolean; unavailableLabel?: string; wiggle?: boolean; onWiggleEnd?: () => void; disabled?: boolean; testId: string; }) { const { t } = useTranslation(["game-misc"]); return (
); }