diff --git a/.editorconfig b/.editorconfig
index deef933..71cadc6 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -10,6 +10,7 @@ charset = utf-8
trim_trailing_whitespace = true
indent_size = 2
indent_style = space
+max_line_length = 120
[*.lua]
indent_size = 4
diff --git a/web/src/App.tsx b/web/src/App.tsx
index b170822..e697d38 100644
--- a/web/src/App.tsx
+++ b/web/src/App.tsx
@@ -3,12 +3,13 @@ import CircleProgressbar from "./features/progress/CircleProgressbar";
import Progressbar from "./features/progress/Progressbar";
import TextUI from "./features/textui/TextUI";
import InputDialog from "./features/dialog/InputDialog";
-import ContextMenu from "./features/menu/ContextMenu";
+import ContextMenu from "./features/menu/context/ContextMenu";
import Settings from "./features/settings";
import { useNuiEvent } from "./hooks/useNuiEvent";
import { setClipboard } from "./utils/setClipboard";
import { fetchNui } from "./utils/fetchNui";
import AlertDialog from "./features/dialog/AlertDialog";
+import ListMenu from "./features/menu/list";
const App: React.FC = () => {
useNuiEvent("setClipboard", (data: string) => {
@@ -27,6 +28,7 @@ const App: React.FC = () => {
+
>
);
};
diff --git a/web/src/features/menu/ContextMenu.tsx b/web/src/features/menu/context/ContextMenu.tsx
similarity index 94%
rename from web/src/features/menu/ContextMenu.tsx
rename to web/src/features/menu/context/ContextMenu.tsx
index 300015d..8e2f6d5 100644
--- a/web/src/features/menu/ContextMenu.tsx
+++ b/web/src/features/menu/context/ContextMenu.tsx
@@ -1,11 +1,11 @@
-import { useNuiEvent } from "../../hooks/useNuiEvent";
+import { useNuiEvent } from "../../../hooks/useNuiEvent";
import { Box, Text, Flex, ScaleFade } from "@chakra-ui/react";
-import { debugData } from "../../utils/debugData";
+import { debugData } from "../../../utils/debugData";
import { useEffect, useState } from "react";
-import { ContextMenuProps } from "../../interfaces/context";
+import { ContextMenuProps } from "../../../interfaces/context";
import Item from "./Item";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { fetchNui } from "../../utils/fetchNui";
+import { fetchNui } from "../../../utils/fetchNui";
debugData([
{
diff --git a/web/src/features/menu/Item.tsx b/web/src/features/menu/context/Item.tsx
similarity index 97%
rename from web/src/features/menu/Item.tsx
rename to web/src/features/menu/context/Item.tsx
index 082146e..28d3cfb 100644
--- a/web/src/features/menu/Item.tsx
+++ b/web/src/features/menu/context/Item.tsx
@@ -12,8 +12,8 @@ import {
HStack,
} from "@chakra-ui/react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Option, ContextMenuProps } from "../../interfaces/context";
-import { fetchNui } from "../../utils/fetchNui";
+import { Option, ContextMenuProps } from "../../../interfaces/context";
+import { fetchNui } from "../../../utils/fetchNui";
const openMenu = (id: string | undefined) => {
fetchNui("openContext", id);
diff --git a/web/src/features/menu/list/index.tsx b/web/src/features/menu/list/index.tsx
new file mode 100644
index 0000000..8f88030
--- /dev/null
+++ b/web/src/features/menu/list/index.tsx
@@ -0,0 +1,119 @@
+import { Box, Spacer, Flex, Stack, Text } from "@chakra-ui/react";
+import { useEffect, useRef, useState } from "react";
+import { useNuiEvent } from "../../../hooks/useNuiEvent";
+import { debugData } from "../../../utils/debugData";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+
+interface MenuSettings {
+ position?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
+ title: string;
+ items: Array<{ label: string; value: string | string[] }>;
+}
+
+debugData([
+ {
+ action: "setMenu",
+ data: {
+ // position: "bottom-left",
+ title: "Vehicle garage",
+ items: [
+ { label: "Option 1", value: "option1" },
+ { label: "Option 2", value: "option2" },
+ { label: "Vehicle class", value: ["Nice", "Super nice", "Extra nice"] },
+ ],
+ },
+ },
+]);
+
+const ListMenu: React.FC = () => {
+ const [menu, setMenu] = useState({
+ position: "top-left",
+ title: "",
+ items: [],
+ });
+ const [selected, setSelected] = useState(0);
+ const [visible, setVisible] = useState(false);
+
+ const moveMenu = (e: KeyboardEvent) => {
+ switch (e.code) {
+ case "ArrowDown":
+ setSelected((selected) => {
+ if (selected >= menu.items.length - 1) return selected;
+ return selected + 1;
+ });
+ break;
+ case "ArrowUp":
+ setSelected((selected) => {
+ if (selected <= 0) return selected;
+ return selected - 1;
+ });
+ break;
+ }
+ };
+
+ useEffect(() => {
+ if (!visible) return document.removeEventListener("keyup", moveMenu);
+
+ document.addEventListener("keyup", moveMenu);
+ }, [visible]);
+
+ useNuiEvent("setMenu", (data: MenuSettings) => {
+ if (!data.position) data.position = "top-left";
+ setMenu(data);
+ setVisible(true);
+ });
+
+ return (
+ <>
+
+
+
+ {menu.title}
+
+
+
+ {menu.items.map((item, index) => (
+
+ {Array.isArray(item.value) ? (
+
+
+
+ {item.label}
+
+ Nice cool
+
+
+
+
+ ) : (
+ item.label
+ )}
+
+ ))}
+
+
+ >
+ );
+};
+
+export default ListMenu;
diff --git a/web/src/index.css b/web/src/index.css
index 5692f71..42c1c45 100644
--- a/web/src/index.css
+++ b/web/src/index.css
@@ -2,13 +2,13 @@
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Fira+Mono&display=swap");
@import url("https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap");
+@import url("https://fonts.googleapis.com/css2?family=Nunito:wght@300;400;500;600;700&display=swap");
body {
background: none !important;
margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
- "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
- sans-serif;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans",
+ "Droid Sans", "Helvetica Neue", sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
height: 100vh;
@@ -21,8 +21,7 @@ body {
}
code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
- monospace;
+ font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
}
@keyframes progress {
@@ -52,13 +51,13 @@ code {
}
.toast-inform {
- background-color: #2980b9;
+ background-color: #2980b9;
}
.toast-success {
- background-color: #27ae60;
+ background-color: #27ae60;
}
.toast-error {
- background-color: #c0392b;
+ background-color: #c0392b;
}