Refactor App.tsx from god component to context-based architecture
All checks were successful
CI / check (push) Successful in 1m18s
CI / build-image (push) Has been skipped

Replace prop drilling with React context providers. App.tsx shrinks
from 427 lines to ~80 lines of pure layout. Components consume shared
state directly via 7 context providers instead of threading 50+ props.

Key changes:
- 7 context providers wrapping existing hooks (encounter, bestiary,
  player characters, side panel, theme, bulk import, initiative rolls)
- 2 coordinating hooks extracted from App.tsx (useInitiativeRolls,
  useAutoStatBlock)
- All 9 affected components refactored from prop-based to context-based
- 6 test files updated to use providers or context mocks
- Prop count enforcement script (max 8 per component interface)
- Constitution principle II-A added (context-based state flow)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-19 14:19:58 +01:00
parent 6584d8d064
commit 8828edf647
34 changed files with 1026 additions and 758 deletions

View File

@@ -8,16 +8,12 @@ import {
} from "react";
import type { CachedSourceInfo } from "../adapters/bestiary-cache.js";
import * as bestiaryCache from "../adapters/bestiary-cache.js";
import { useBestiaryContext } from "../contexts/bestiary-context.js";
import { Button } from "./ui/button.js";
import { Input } from "./ui/input.js";
interface SourceManagerProps {
onCacheCleared: () => void;
}
export function SourceManager({
onCacheCleared,
}: Readonly<SourceManagerProps>) {
export function SourceManager() {
const { refreshCache } = useBestiaryContext();
const [sources, setSources] = useState<CachedSourceInfo[]>([]);
const [filter, setFilter] = useState("");
const [optimisticSources, applyOptimistic] = useOptimistic(
@@ -44,14 +40,14 @@ export function SourceManager({
applyOptimistic({ type: "remove", sourceCode });
await bestiaryCache.clearSource(sourceCode);
await loadSources();
onCacheCleared();
void refreshCache();
};
const handleClearAll = async () => {
applyOptimistic({ type: "clear" });
await bestiaryCache.clearAll();
await loadSources();
onCacheCleared();
void refreshCache();
};
const filteredSources = useMemo(() => {