Complete SQL diagnostics and editor accessibility
This commit is contained in:
@@ -54,6 +54,7 @@ export default function DataflowCanvas({
|
||||
onGraphChange,
|
||||
onSelectNode
|
||||
}: DataflowCanvasProps) {
|
||||
const canvasRef = useRef<HTMLDivElement | null>(null);
|
||||
const [instance, setInstance] = useState<ReactFlowInstance<DataflowFlowNode, Edge> | null>(null);
|
||||
const [proximityEdge, setProximityEdge] = useState<Edge | null>(null);
|
||||
const [selectedEdgeId, setSelectedEdgeId] = useState<string | null>(null);
|
||||
@@ -129,6 +130,24 @@ export default function DataflowCanvas({
|
||||
});
|
||||
};
|
||||
|
||||
const restoreFocusAfterRemoval = (removedNodeIds: Set<string>) => {
|
||||
const focusedNodeId = document.activeElement
|
||||
?.closest<HTMLElement>(".react-flow__node")
|
||||
?.dataset.id;
|
||||
if (!focusedNodeId || !removedNodeIds.has(focusedNodeId)) return;
|
||||
const removedIndex = graph.nodes.findIndex((node) => node.id === focusedNodeId);
|
||||
const remainingNodes = graph.nodes.filter((node) => !removedNodeIds.has(node.id));
|
||||
const nextNode = remainingNodes[Math.min(Math.max(0, removedIndex), remainingNodes.length - 1)];
|
||||
requestAnimationFrame(() => {
|
||||
const nextElement = nextNode
|
||||
? canvasRef.current?.querySelector<HTMLElement>(
|
||||
`.react-flow__node[data-id="${CSS.escape(nextNode.id)}"]`
|
||||
)
|
||||
: null;
|
||||
(nextElement ?? canvasRef.current)?.focus();
|
||||
});
|
||||
};
|
||||
|
||||
const updateEdges = (nextEdges: Edge[]) => {
|
||||
onGraphChange({
|
||||
...graph,
|
||||
@@ -206,7 +225,10 @@ export default function DataflowCanvas({
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={canvasRef}
|
||||
className="dataflow-canvas"
|
||||
tabIndex={0}
|
||||
aria-label="Dataflow graph canvas"
|
||||
onDragOver={(event) => {
|
||||
if (event.dataTransfer.types.includes("application/x-govoplan-dataflow-node")) {
|
||||
event.preventDefault();
|
||||
@@ -224,6 +246,11 @@ export default function DataflowCanvas({
|
||||
if (readOnly) return;
|
||||
const graphChanges = changes.filter((change) => change.type !== "dimensions");
|
||||
if (graphChanges.length) {
|
||||
restoreFocusAfterRemoval(new Set(
|
||||
graphChanges
|
||||
.filter((change) => change.type === "remove")
|
||||
.map((change) => change.id)
|
||||
));
|
||||
updateNodes(applyNodeChanges(graphChanges, nodes));
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -2221,7 +2221,13 @@ function DiagnosticsPanel({
|
||||
<strong>{item.code}</strong>
|
||||
<small>{item.message}</small>
|
||||
</span>
|
||||
{item.node_id ? <code>{item.node_id}</code> : null}
|
||||
{item.node_id ? (
|
||||
<code>{item.node_id}</code>
|
||||
) : item.source_location ? (
|
||||
<code>
|
||||
{item.source_location.start_line}:{item.source_location.start_column}
|
||||
</code>
|
||||
) : null}
|
||||
</div>
|
||||
))}
|
||||
{nodeDiagnostics.map((item) => (
|
||||
|
||||
Reference in New Issue
Block a user