Files
healer-man/src/ui/DungeonInteractionPrompt.tsx
T
2026-09-14 13:20:20 -04:00

45 lines
1.7 KiB
TypeScript

import { useSyncExternalStore } from "react";
import {
activeDungeonEncounterRevision,
subscribeDungeonEncounterSnapshots,
} from "../game/dungeonEncounterRuntime";
import {
activeDungeonInteractionCandidate,
interactWithActiveDungeonObject,
} from "../game/dungeonWorldInteraction";
import { useGameStore } from "../game/store";
import { useInputBindingLabels } from "../input/useInputBindingLabels";
export function DungeonInteractionPrompt({ interaction, onInteract }: {
interaction?: { prompt: string; name: string; label: string } | null;
onInteract?: () => void;
} = {}) {
const label = useInputBindingLabels();
const playerPosition = useGameStore((state) => state.playerPosition);
const inputMode = useGameStore((state) => state.inputMode);
const overlay = useGameStore((state) => state.overlay);
useSyncExternalStore(
subscribeDungeonEncounterSnapshots,
activeDungeonEncounterRevision,
activeDungeonEncounterRevision,
);
void playerPosition;
const local = interaction === undefined && !overlay ? activeDungeonInteractionCandidate() : null;
const candidate = interaction ?? (local ? { prompt: local.object.interaction!.prompt, name: local.object.name, label: local.state.label } : null);
if (!candidate) return null;
return (
<button
type="button"
className="dungeon-interaction-prompt"
onClick={onInteract ?? (() => interactWithActiveDungeonObject())}
aria-label={`${candidate.prompt}: ${candidate.name}`}
>
<span className="dungeon-interaction-prompt__key">{label(inputMode === "gamepad" ? "controller" : "pc", "loot")}</span>
<span>
<strong>{candidate.prompt}</strong>
<small>{candidate.name} · {candidate.label}</small>
</span>
</button>
);
}