import { useEffect, useRef } from 'react'; import { parseFenMeta } from '../engine/pgnFormat.js'; import { buildMoveListItems, buildVariation } from '../engine/moveLine.js'; import { scrollIntoViewWithin } from '../engine/scroll.js'; import Button from './ui/Button.jsx'; import Panel from './ui/Panel.jsx'; function MoveButton({ node, isCurrent, chip, onGoTo }) { const cls = `move-line__move${chip ? ' move-line__move--chip' : ''}${isCurrent ? ' is-current' : ''}`; return ; } function renderItems(items, nodes, rootChildren, currentId, onGoTo, keyPrefix) { return items.flatMap((item, idx) => { const key = `${keyPrefix}-${idx}`; if (item.kind === 'row') { const whiteEmpty = !item.white || item.white.placeholder; return [
{item.num}. onGoTo(item.white.node.id) : undefined} > {item.white?.placeholder ? '...' : null} {item.white && !item.white.placeholder && } onGoTo(item.black.node.id) : undefined} > {item.black && }
, ]; } if (item.kind === 'para') { return [
{item.chips.map((chip, ci) => chip.kind === 'num' ? {chip.text} : )}
, ]; } // 'variation' marker - expand lazily so nested forks don't need to // be walked until they're actually reached. const varItems = buildVariation(nodes, rootChildren, item.nodeIds, item.whiteToMove, item.moveNum, currentId, item.depth); return renderItems(varItems, nodes, rootChildren, currentId, onGoTo, `${key}-v`); }); } export default function PgnPanel({ explorer }) { const { moveHistory, startFen, historyInitialized, actions } = explorer; const { nodes, rootChildren, currentId } = moveHistory; const scrollRef = useRef(null); useEffect(() => { const container = scrollRef.current; const current = container?.querySelector('.is-current'); scrollIntoViewWithin(current, container); }, [currentId, nodes]); let content = null; if (!historyInitialized) { content = null; // no render until Board reports its first move-tree change } else if (!rootChildren || rootChildren.length === 0) { content = No moves yet; } else { const { turn, fullmove } = parseFenMeta(startFen); const items = buildMoveListItems(nodes, rootChildren, currentId, turn, fullmove); content = renderItems(items, nodes, rootChildren, currentId, actions.goToNode, 'm'); } return ( } >
{content}
); }