File size: 2,907 Bytes
5365cac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4a674c0
 
5365cac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
be99f83
5365cac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { useCallback, useRef, useState } from 'react';
import { NodeMouseHandler, useReactFlow } from 'reactflow';

import styles from './index.less';

export interface INodeContextMenu {
  id: string;
  top: number;
  left: number;
  right?: number;
  bottom?: number;
  [key: string]: unknown;
}

export function NodeContextMenu({
  id,
  top,
  left,
  right,
  bottom,
  ...props
}: INodeContextMenu) {
  const { getNode, setNodes, addNodes, setEdges } = useReactFlow();

  const duplicateNode = useCallback(() => {
    const node = getNode(id);
    const position = {
      x: node?.position?.x || 0 + 50,
      y: node?.position?.y || 0 + 50,
    };

    addNodes({
      ...(node || {}),
      data: node?.data,
      selected: false,
      dragging: false,
      id: `${node?.id}-copy`,
      position,
    });
  }, [id, getNode, addNodes]);

  const deleteNode = useCallback(() => {
    setNodes((nodes) => nodes.filter((node) => node.id !== id));
    setEdges((edges) => edges.filter((edge) => edge.source !== id));
  }, [id, setNodes, setEdges]);

  return (
    <div
      style={{ top, left, right, bottom }}
      className={styles.contextMenu}
      {...props}
    >
      <p style={{ margin: '0.5em' }}>
        <small>node: {id}</small>
      </p>
      <button onClick={duplicateNode} type={'button'}>
        duplicate
      </button>
      <button onClick={deleteNode} type={'button'}>
        delete
      </button>
    </div>
  );
}

/*  @deprecated
 */
export const useHandleNodeContextMenu = (sideWidth: number) => {
  const [menu, setMenu] = useState<INodeContextMenu>({} as INodeContextMenu);
  const ref = useRef<any>(null);

  const onNodeContextMenu: NodeMouseHandler = useCallback(
    (event, node) => {
      // Prevent native context menu from showing
      event.preventDefault();

      // Calculate position of the context menu. We want to make sure it
      // doesn't get positioned off-screen.
      const pane = ref.current?.getBoundingClientRect();
      // setMenu({
      //   id: node.id,
      //   top: event.clientY < pane.height - 200 ? event.clientY : 0,
      //   left: event.clientX < pane.width - 200 ? event.clientX : 0,
      //   right: event.clientX >= pane.width - 200 ? pane.width - event.clientX : 0,
      //   bottom:
      //     event.clientY >= pane.height - 200 ? pane.height - event.clientY : 0,
      // });

      setMenu({
        id: node.id,
        top: event.clientY - 144,
        left: event.clientX - sideWidth,
        // top: event.clientY < pane.height - 200 ? event.clientY - 72 : 0,
        // left: event.clientX < pane.width - 200 ? event.clientX : 0,
      });
    },
    [sideWidth],
  );

  // Close the context menu if it's open whenever the window is clicked.
  const onPaneClick = useCallback(
    () => setMenu({} as INodeContextMenu),
    [setMenu],
  );

  return { onNodeContextMenu, menu, onPaneClick, ref };
};