59 lines
1.8 KiB
TypeScript
59 lines
1.8 KiB
TypeScript
/**
|
|
* Canvas host: mounts the JointJS paper via EditorController and accepts
|
|
* palette drops.
|
|
*/
|
|
|
|
import { useEffect, useRef } from 'react';
|
|
import { EditorController } from '../editor/paper';
|
|
import { PALETTE_MIME } from './Palette';
|
|
import { getState, setState, bumpGraphVersion, applySimulationResult } from '../state/store';
|
|
|
|
interface CanvasProps {
|
|
onReady(controller: EditorController): void;
|
|
}
|
|
|
|
export function Canvas({ onReady }: CanvasProps) {
|
|
const hostRef = useRef<HTMLDivElement>(null);
|
|
const controllerRef = useRef<EditorController | null>(null);
|
|
|
|
useEffect(() => {
|
|
const host = hostRef.current;
|
|
if (!host || controllerRef.current) return;
|
|
const controller = new EditorController(host, getState().config, {
|
|
onSelectionChange: (selection) => setState({ selection }),
|
|
onGraphChange: () => bumpGraphVersion(),
|
|
onHistoryChange: (canUndo, canRedo) => setState({ canUndo, canRedo }),
|
|
onSimulationChange: (running, result) => applySimulationResult(running, result),
|
|
});
|
|
controllerRef.current = controller;
|
|
onReady(controller);
|
|
return () => {
|
|
controller.dispose();
|
|
controllerRef.current = null;
|
|
};
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
|
|
return (
|
|
<div
|
|
ref={hostRef}
|
|
className="pf-canvas"
|
|
data-testid="canvas"
|
|
onDragOver={(e) => {
|
|
if (e.dataTransfer.types.includes(PALETTE_MIME)) {
|
|
e.preventDefault();
|
|
e.dataTransfer.dropEffect = 'copy';
|
|
}
|
|
}}
|
|
onDrop={(e) => {
|
|
const typeId = e.dataTransfer.getData(PALETTE_MIME);
|
|
const controller = controllerRef.current;
|
|
if (!typeId || !controller) return;
|
|
e.preventDefault();
|
|
const p = controller.clientToLocal(e.clientX, e.clientY);
|
|
controller.addNode(typeId, p.x, p.y);
|
|
}}
|
|
/>
|
|
);
|
|
}
|