yansari's picture
feat: intro page, undo/redo, transition fix, naming and stats polish
e0e4431
Raw
History Blame Contribute Delete
2.82 kB
import type { InteractionMode } from '../types';
import { NODE_TYPES, NODE_COLORS, NODE_TYPE_LABELS } from '../constants';
interface Props {
mode: InteractionMode;
addNodeType: string;
onAddNodeTypeChange: (type: string) => void;
onSetMode: (mode: InteractionMode) => void;
onUndo: () => void;
onRedo: () => void;
undoCount: number;
redoCount: number;
}
const HINTS: Partial<Record<InteractionMode, string>> = {
'add-node': 'Click an empty spot on the graph to drop a node.',
'add-edge': 'Click one node, then another, to connect them.',
delete: 'Click any node or edge to remove it.',
};
export default function EditPanel({
mode,
addNodeType,
onAddNodeTypeChange,
onSetMode,
onUndo,
onRedo,
undoCount,
redoCount,
}: Props) {
const tool = (m: InteractionMode, label: string) => (
<button
className={`edit-tool${mode === m ? ' active' : ''}`}
onClick={() => onSetMode(mode === m ? 'idle' : m)}
>
{label}
</button>
);
return (
<div className="panel">
<h3>Edit Graph</h3>
<p className="route-hint">
Fix extraction defects by hand. Add or remove nodes and edges directly on
the canvas.
</p>
<div className="edit-tools">
{tool('add-node', 'Add Node')}
{tool('add-edge', 'Add Edge')}
{tool('delete', 'Delete')}
</div>
{mode === 'add-node' && (
<div className="edit-nodetype">
<label className="stage-label">New node type</label>
<div className="nodetype-grid">
{NODE_TYPES.map((t) => (
<button
key={t}
className={`nodetype-chip${addNodeType === t ? ' active' : ''}`}
onClick={() => onAddNodeTypeChange(t)}
>
<span className="type-swatch" style={{ backgroundColor: NODE_COLORS[t] }} />
{NODE_TYPE_LABELS[t]}
</button>
))}
</div>
</div>
)}
{HINTS[mode] && <div className="edit-hint">{HINTS[mode]}</div>}
<div className="route-buttons" style={{ marginTop: 10 }}>
<button className="btn" onClick={onUndo} disabled={undoCount === 0}>
Undo{undoCount > 0 ? ` (${undoCount})` : ''}
</button>
<button className="btn" onClick={onRedo} disabled={redoCount === 0}>
Redo{redoCount > 0 ? ` (${redoCount})` : ''}
</button>
</div>
<button
className="btn btn-block"
style={{ marginTop: 8 }}
onClick={() => onSetMode('idle')}
disabled={mode === 'idle'}
>
Done Editing
</button>
<p className="edit-undo-note">
Every change is undoable and redoable, all the way back to the originally
extracted graph.
</p>
</div>
);
}