import { useEffect, useRef } from "react"; import { ActionBar } from "./components/action-bar.js"; import { BulkImportToasts } from "./components/bulk-import-toasts.js"; import { CombatantRow } from "./components/combatant-row.js"; import { PlayerCharacterSection, type PlayerCharacterSectionHandle, } from "./components/player-character-section.js"; import { StatBlockPanel } from "./components/stat-block-panel.js"; import { Toast } from "./components/toast.js"; import { TurnNavigation } from "./components/turn-navigation.js"; import { useEncounterContext } from "./contexts/encounter-context.js"; import { useInitiativeRollsContext } from "./contexts/initiative-rolls-context.js"; import { useSidePanelContext } from "./contexts/side-panel-context.js"; import { useActionBarAnimation } from "./hooks/use-action-bar-animation.js"; import { useAutoStatBlock } from "./hooks/use-auto-stat-block.js"; import { cn } from "./lib/utils.js"; export function App() { const { encounter, isEmpty } = useEncounterContext(); const sidePanel = useSidePanelContext(); const rolls = useInitiativeRollsContext(); useAutoStatBlock(); const playerCharacterRef = useRef(null); const actionBarInputRef = useRef(null); const activeRowRef = useRef(null); const actionBarAnim = useActionBarAnimation(encounter.combatants.length); // Auto-scroll to active combatant when turn changes const activeIndex = encounter.activeIndex; useEffect(() => { if (activeIndex >= 0) { activeRowRef.current?.scrollIntoView({ block: "nearest", behavior: "smooth", }); } }, [activeIndex]); return (
{!!actionBarAnim.showTopBar && (
)} {isEmpty ? (
playerCharacterRef.current?.openManagement() } autoFocus />
) : ( <>
{encounter.combatants.map((c, i) => ( ))}
playerCharacterRef.current?.openManagement() } />
)}
{!!sidePanel.pinnedCreatureId && sidePanel.isWideDesktop && ( )} {rolls.rollSkippedCount > 0 && ( )} {!!rolls.rollSingleSkipped && ( )}
); }