// Draggable node with avatar
function Node({
node, selected, onSelect, onDrag, onDragEnd,
onStartConnect, onFinishConnect, onDelete,
dragging, worldZoom
}){
const ref = React.useRef(null);
const moveState = React.useRef(null);
const onPointerDown = (e) => {
if (e.target.closest('.connect-handle')) return;
if (e.target.closest('.delete-btn')) return;
e.stopPropagation();
onSelect(node.id);
const startX = e.clientX, startY = e.clientY;
const ox = node.x, oy = node.y;
moveState.current = { startX, startY, ox, oy, moved:false };
e.currentTarget.setPointerCapture(e.pointerId);
};
const onPointerMove = (e) => {
if (!moveState.current) return;
const { startX, startY, ox, oy } = moveState.current;
const dx = (e.clientX - startX) / worldZoom;
const dy = (e.clientY - startY) / worldZoom;
if (Math.abs(dx)+Math.abs(dy) > 2) moveState.current.moved = true;
onDrag(node.id, ox+dx, oy+dy);
};
const onPointerUp = (e) => {
if (!moveState.current) return;
const moved = moveState.current.moved;
moveState.current = null;
onDragEnd(node.id, moved);
try { e.currentTarget.releasePointerCapture(e.pointerId); } catch(_){}
};
const handleConnectDown = (e) => {
e.stopPropagation();
e.preventDefault();
onStartConnect(node.id, e);
};
const handleFinishUp = (e) => {
// If currently connecting, finish here. Parent handles routing on pointerup too.
onFinishConnect(node.id);
};
const shapeClass = node.shape || 'circle';
const avatarStyle = { background: node.color || '#fff' };
let inner;
if (node.image){
inner = ;
} else if (node.emoji){
inner =