training_data/packages/ui/src/components/mindmap/MindMapNode.tsx

83 lines
2.6 KiB
TypeScript
Raw Normal View History

2025-01-10 21:36:17 +08:00
import { Handle, NodeProps, Position, useEdges } from '@xyflow/react';
import { MindMapNodeType } from './types';
import useMindMapStore, { RFState } from './store';
import { useEffect, useRef, useState } from 'react';
import { useShallow } from 'zustand/shallow';
import { useClickOutside } from '../../hooks/useClickOutside';
import { useHotkeys } from 'react-hotkeys-hook';
const selector = (state: RFState) => ({
selectedNodeId: state.selectedNodeId,
editingNodeId: state.editingNodeId,
updateNodeLabel: state.updateNodeLabel,
setSelectedNodeId: state.setSelectedNodeId,
setEditingNodeId: state.setEditingNodeId
});
function MindMapNode({ id, data }: NodeProps<MindMapNodeType>) {
const nodeRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
const [inputValue, setInputValue] = useState(data.label);
const {
updateNodeLabel,
selectedNodeId,
setSelectedNodeId,
setEditingNodeId,
editingNodeId
} = useMindMapStore(useShallow(selector));
useEffect(() => {
if (editingNodeId === id) {
setEditingNodeId(id);
setInputValue(data.label);
setTimeout(() => {
inputRef.current?.focus();
inputRef.current?.select();
}, 0);
} else {
inputRef.current?.blur()
}
}, [editingNodeId])
const handleDoubleClick = (e: React.MouseEvent) => {
e.stopPropagation();
setEditingNodeId(id)
};
useHotkeys("space", (e) => {
if (selectedNodeId === id)
setEditingNodeId(id)
}, { preventDefault: true });
const handleClick = (e: React.MouseEvent) => {
setSelectedNodeId(id);
};
useClickOutside(nodeRef, () => {
console.log(selectedNodeId, id)
if (selectedNodeId === id)
setSelectedNodeId(null)
if (editingNodeId === id) {
setEditingNodeId(null)
updateNodeLabel(id, inputValue)
}
});
return (
<div
ref={nodeRef}
onDoubleClick={handleDoubleClick}
onClick={handleClick}
className={`mindmap-node ${id === selectedNodeId ? 'selected' : ''}`}
>
<input
ref={inputRef}
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
className="input"
readOnly={id !== editingNodeId}
/>
<Handle type="target" position={Position.Top} />
<Handle type="source" position={Position.Top} />
</div>
);
}
export default MindMapNode;