File size: 4,484 Bytes
f909d7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import React from "react";
import { Menu, Flex, Text } from "@mantine/core";
import { useHotkeys } from "@mantine/hooks";
import ReactGA from "react-ga4";
import toast from "react-hot-toast";
import { CgChevronDown, CgArrowsShrinkH, CgArrowsMergeAltH } from "react-icons/cg";
import { VscExpandAll, VscCollapseAll, VscTarget } from "react-icons/vsc";
import useToggleHide from "src/hooks/useToggleHide";
import { getNextDirection } from "src/lib/utils/graph/getNextDirection";
import useGraph from "src/store/useGraph";
import * as Styles from "./styles";

function rotateLayout(direction: "LEFT" | "RIGHT" | "DOWN" | "UP") {
  if (direction === "LEFT") return 90;
  if (direction === "UP") return 180;
  if (direction === "RIGHT") return 270;
  return 360;
}

export const ViewMenu = () => {
  const { validateHiddenNodes } = useToggleHide();
  const [coreKey, setCoreKey] = React.useState("CTRL");
  const toggleFold = useGraph(state => state.toggleFold);
  const setDirection = useGraph(state => state.setDirection);
  const direction = useGraph(state => state.direction);
  const expandGraph = useGraph(state => state.expandGraph);
  const collapseGraph = useGraph(state => state.collapseGraph);
  const focusFirstNode = useGraph(state => state.focusFirstNode);
  const foldNodes = useGraph(state => state.foldNodes);
  const graphCollapsed = useGraph(state => state.graphCollapsed);

  const toggleFoldNodes = () => {
    toggleFold(!foldNodes);
    toast(`${foldNodes ? "Unfolded" : "Folded"} nodes`);
  };

  const toggleDirection = () => {
    const nextDirection = getNextDirection(direction || "RIGHT");
    if (setDirection) setDirection(nextDirection);
  };

  const toggleExpandCollapseGraph = () => {
    if (graphCollapsed) expandGraph();
    else collapseGraph();

    validateHiddenNodes();
    toast(`${graphCollapsed ? "Expanded" : "Collapsed"} graph.`);
  };

  useHotkeys([
    ["mod+shift+d", toggleDirection],
    ["mod+shift+f", toggleFoldNodes],
    ["mod+shift+c", toggleExpandCollapseGraph],
    [
      "mod+f",
      () => {
        const input = document.querySelector("#search-node") as HTMLInputElement;
        input.focus();
      },
    ],
  ]);

  React.useEffect(() => {
    if (typeof window !== "undefined") {
      setCoreKey(navigator.userAgent.indexOf("Mac OS X") ? "⌘" : "CTRL");
    }
  }, []);

  return (
    <Menu shadow="md" closeOnItemClick={false} withArrow>
      <Menu.Target>
        <Styles.StyledToolElement>
          <Flex align="center" gap={3}>
            View <CgChevronDown />
          </Flex>
        </Styles.StyledToolElement>
      </Menu.Target>
      <Menu.Dropdown>
        <Menu.Item
          fz={12}
          onClick={() => {
            toggleDirection();
            ReactGA.event({
              action: "toggle_layout_direction",
              category: "User",
              label: "Tools",
            });
          }}
          leftSection={<Styles.StyledFlowIcon rotate={rotateLayout(direction || "RIGHT")} />}
          rightSection={
            <Text ml="md" fz={10} c="dimmed">
              {coreKey} Shift D
            </Text>
          }
        >
          Rotate Layout
        </Menu.Item>
        <Menu.Item
          fz={12}
          onClick={() => {
            toggleFoldNodes();
            ReactGA.event({
              action: "toggle_fold_nodes",
              category: "User",
              label: "Tools",
            });
          }}
          leftSection={foldNodes ? <CgArrowsShrinkH /> : <CgArrowsMergeAltH />}
          rightSection={
            <Text ml="md" fz={10} c="dimmed">
              {coreKey} Shift F
            </Text>
          }
        >
          {foldNodes ? "Unfold" : "Fold"} Nodes
        </Menu.Item>
        <Menu.Item
          fz={12}
          onClick={() => {
            toggleExpandCollapseGraph();
            ReactGA.event({
              action: "toggle_collapse_nodes",
              category: "User",
              label: "Tools",
            });
          }}
          leftSection={graphCollapsed ? <VscExpandAll /> : <VscCollapseAll />}
          rightSection={
            <Text ml="md" fz={10} c="dimmed">
              {coreKey} Shift C
            </Text>
          }
        >
          {graphCollapsed ? "Expand" : "Collapse"} Nodes
        </Menu.Item>
        <Menu.Item fz={12} onClick={focusFirstNode} leftSection={<VscTarget />}>
          Focus to First Node
        </Menu.Item>
      </Menu.Dropdown>
    </Menu>
  );
};