dirk-cfx-react 1.1.58 → 1.1.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/index.cjs +287 -63
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.cts +64 -16
- package/dist/components/index.d.ts +64 -16
- package/dist/components/index.js +287 -64
- package/dist/components/index.js.map +1 -1
- package/dist/hooks/index.cjs +41 -26
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.cts +27 -19
- package/dist/hooks/index.d.ts +27 -19
- package/dist/hooks/index.js +40 -25
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.cjs +332 -89
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +330 -88
- package/dist/index.js.map +1 -1
- package/dist/providers/index.cjs +78 -2
- package/dist/providers/index.cjs.map +1 -1
- package/dist/providers/index.js +79 -3
- package/dist/providers/index.js.map +1 -1
- package/dist/utils/index.cjs +26 -6
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +4 -1
- package/dist/utils/index.d.ts +4 -1
- package/dist/utils/index.js +26 -6
- package/dist/utils/index.js.map +1 -1
- package/package.json +113 -113
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { Flex, Text, Image as Image$1, createTheme, Box, Stack, Title as Title$1, Code, TextInput, Select, useMantineTheme, alpha, Progress, RingProgress, Portal, Button, Loader, MantineProvider, BackgroundImage, Group, JsonInput } from '@mantine/core';
|
|
1
|
+
import { Flex, Text, Image as Image$1, createTheme, Box, Stack, Title as Title$1, Code, TextInput, Select, useMantineTheme, Tooltip, alpha, Progress, RingProgress, Portal, Button, Loader, ActionIcon, MantineProvider, BackgroundImage, Group, JsonInput } from '@mantine/core';
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import React5, { createContext, useContext, useEffect, useRef, useState, useMemo, useLayoutEffect } from 'react';
|
|
4
4
|
import { create, useStore, createStore } from 'zustand';
|
|
5
5
|
import axios from 'axios';
|
|
6
6
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
7
7
|
import { motion, AnimatePresence, useMotionValue } from 'framer-motion';
|
|
8
|
+
import { Info, X, AlertTriangle, Trash2, Check, FlaskConical, ChevronUp, ChevronDown, ArrowLeft, Undo2, Redo2, Save, History, XCircle, Code2, RotateCcw, Search, Filter, User } from 'lucide-react';
|
|
8
9
|
import clickSoundUrl from './click_sound-PNCRRTM4.mp3';
|
|
9
10
|
import hoverSoundUrl from './hover_sound-NBUA222C.mp3';
|
|
10
|
-
import { X, AlertTriangle, Trash2, Check, Undo2, Redo2, Save, History, XCircle, Code2, RotateCcw, Search, Filter, User, ChevronDown } from 'lucide-react';
|
|
11
11
|
import { QueryClient, QueryClientProvider, useInfiniteQuery } from '@tanstack/react-query';
|
|
12
12
|
import '@mantine/core/styles.css';
|
|
13
13
|
import '@mantine/notifications/styles.css';
|
|
@@ -1306,8 +1306,12 @@ async function fetchNui(eventName, data, mockData) {
|
|
|
1306
1306
|
}
|
|
1307
1307
|
const overrideResourceName = useSettings.getState().overideResourceName;
|
|
1308
1308
|
const resourceName = window.GetParentResourceName ? window.GetParentResourceName() : overrideResourceName ? overrideResourceName : "dirk-cfx-react";
|
|
1309
|
-
|
|
1310
|
-
|
|
1309
|
+
try {
|
|
1310
|
+
const resp = await fetch(`https://${resourceName}/${eventName}`, options);
|
|
1311
|
+
return await resp.json();
|
|
1312
|
+
} catch {
|
|
1313
|
+
return mockData ?? {};
|
|
1314
|
+
}
|
|
1311
1315
|
}
|
|
1312
1316
|
var initialFetches = {};
|
|
1313
1317
|
async function registerInitialFetch(eventName, data, mockData) {
|
|
@@ -1326,10 +1330,8 @@ async function runFetches() {
|
|
|
1326
1330
|
var useAutoFetcher = () => {
|
|
1327
1331
|
useEffect(() => {
|
|
1328
1332
|
if (isEnvBrowser()) return;
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
};
|
|
1332
|
-
run();
|
|
1333
|
+
runFetches().catch(() => {
|
|
1334
|
+
});
|
|
1333
1335
|
}, []);
|
|
1334
1336
|
};
|
|
1335
1337
|
var fetchLuaTable = (tableName, mockData) => {
|
|
@@ -1356,6 +1358,13 @@ var internalEvent = (events, timer = 1e3) => {
|
|
|
1356
1358
|
}
|
|
1357
1359
|
}
|
|
1358
1360
|
};
|
|
1361
|
+
var reportedMissing = /* @__PURE__ */ new Set();
|
|
1362
|
+
function reportMissingLocale(key) {
|
|
1363
|
+
if (!key || reportedMissing.has(key)) return;
|
|
1364
|
+
reportedMissing.add(key);
|
|
1365
|
+
fetchNui("REPORT_MISSING_LOCALE", { key }).catch(() => {
|
|
1366
|
+
});
|
|
1367
|
+
}
|
|
1359
1368
|
var localeStore = create((set, get) => {
|
|
1360
1369
|
return {
|
|
1361
1370
|
locales: {
|
|
@@ -1363,6 +1372,7 @@ var localeStore = create((set, get) => {
|
|
|
1363
1372
|
},
|
|
1364
1373
|
locale: (key, ...args) => {
|
|
1365
1374
|
const exists = get().locales[key];
|
|
1375
|
+
if (!exists) reportMissingLocale(key);
|
|
1366
1376
|
let translation = exists || key;
|
|
1367
1377
|
if (args.length) {
|
|
1368
1378
|
translation = translation.replace(/%s/g, () => String(args.shift() || ""));
|
|
@@ -1374,7 +1384,16 @@ var localeStore = create((set, get) => {
|
|
|
1374
1384
|
var locale = localeStore.getState().locale;
|
|
1375
1385
|
registerInitialFetch("GET_LOCALES", void 0).then((data) => {
|
|
1376
1386
|
localeStore.setState({ locales: data });
|
|
1387
|
+
}).catch(() => {
|
|
1377
1388
|
});
|
|
1389
|
+
if (typeof window !== "undefined") {
|
|
1390
|
+
window.addEventListener("message", (event) => {
|
|
1391
|
+
const msg = event.data;
|
|
1392
|
+
if (!msg || msg.action !== "UPDATE_DIRK_LIB_LOCALES") return;
|
|
1393
|
+
if (!msg.data || typeof msg.data !== "object") return;
|
|
1394
|
+
localeStore.setState({ locales: msg.data });
|
|
1395
|
+
});
|
|
1396
|
+
}
|
|
1378
1397
|
|
|
1379
1398
|
// src/utils/map.ts
|
|
1380
1399
|
var mapCenter = [-119.43, 58.84];
|
|
@@ -1891,6 +1910,7 @@ registerInitialFetch("FETCH_ALL_ITEMS", null, {
|
|
|
1891
1910
|
}).then((fetchedItems) => {
|
|
1892
1911
|
if (!fetchedItems) return;
|
|
1893
1912
|
useItems.setState(fetchedItems);
|
|
1913
|
+
}).catch(() => {
|
|
1894
1914
|
});
|
|
1895
1915
|
|
|
1896
1916
|
// src/utils/inputMapper.ts
|
|
@@ -2536,8 +2556,8 @@ function InputContainer(props) {
|
|
|
2536
2556
|
(props.title || props.description) && /* @__PURE__ */ jsxs(
|
|
2537
2557
|
Flex,
|
|
2538
2558
|
{
|
|
2539
|
-
|
|
2540
|
-
|
|
2559
|
+
align: "center",
|
|
2560
|
+
flex: 1,
|
|
2541
2561
|
p: props.p == "0" ? "sm" : 0,
|
|
2542
2562
|
children: [
|
|
2543
2563
|
props.title && /* @__PURE__ */ jsx(
|
|
@@ -2554,12 +2574,26 @@ function InputContainer(props) {
|
|
|
2554
2574
|
}
|
|
2555
2575
|
),
|
|
2556
2576
|
props.description && /* @__PURE__ */ jsx(
|
|
2557
|
-
|
|
2577
|
+
Tooltip,
|
|
2558
2578
|
{
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2579
|
+
label: props.description,
|
|
2580
|
+
position: "top-end",
|
|
2581
|
+
withArrow: true,
|
|
2582
|
+
multiline: true,
|
|
2583
|
+
maw: "22vh",
|
|
2584
|
+
styles: {
|
|
2585
|
+
tooltip: {
|
|
2586
|
+
background: alpha(theme2.colors.dark[7], 0.95),
|
|
2587
|
+
border: `0.1vh solid rgba(255,255,255,0.1)`,
|
|
2588
|
+
color: "rgba(255,255,255,0.75)",
|
|
2589
|
+
fontFamily: "Akrobat Bold",
|
|
2590
|
+
fontSize: "1.3vh",
|
|
2591
|
+
lineHeight: 1.3,
|
|
2592
|
+
padding: "0.6vh 0.8vh",
|
|
2593
|
+
letterSpacing: "0.03em"
|
|
2594
|
+
}
|
|
2595
|
+
},
|
|
2596
|
+
children: /* @__PURE__ */ jsx(Flex, { align: "center", justify: "center", style: { marginLeft: "auto", cursor: "help" }, children: /* @__PURE__ */ jsx(Info, { size: "1.6vh", color: alpha(theme2.colors[theme2.primaryColor][5], 0.45) }) })
|
|
2563
2597
|
}
|
|
2564
2598
|
)
|
|
2565
2599
|
]
|
|
@@ -2576,13 +2610,7 @@ function InputContainer(props) {
|
|
|
2576
2610
|
children: props.error
|
|
2577
2611
|
}
|
|
2578
2612
|
),
|
|
2579
|
-
/* @__PURE__ */ jsx(
|
|
2580
|
-
Flex,
|
|
2581
|
-
{
|
|
2582
|
-
ml: "auto",
|
|
2583
|
-
children: props.rightSection
|
|
2584
|
-
}
|
|
2585
|
-
)
|
|
2613
|
+
props.rightSection && /* @__PURE__ */ jsx(Flex, { children: props.rightSection })
|
|
2586
2614
|
]
|
|
2587
2615
|
}
|
|
2588
2616
|
),
|
|
@@ -3273,7 +3301,7 @@ function Modal({
|
|
|
3273
3301
|
children: description2
|
|
3274
3302
|
}
|
|
3275
3303
|
) }),
|
|
3276
|
-
children
|
|
3304
|
+
/* @__PURE__ */ jsx("div", { style: { flex: 1, minHeight: 0, display: "flex", flexDirection: "column" }, children })
|
|
3277
3305
|
]
|
|
3278
3306
|
}
|
|
3279
3307
|
)
|
|
@@ -3955,42 +3983,42 @@ var useNuiEvent = (action, handler) => {
|
|
|
3955
3983
|
}, [action]);
|
|
3956
3984
|
};
|
|
3957
3985
|
var _instance = null;
|
|
3958
|
-
function
|
|
3959
|
-
if (!_instance) throw new Error("[dirk-cfx-react]
|
|
3986
|
+
function getScriptConfigInstance() {
|
|
3987
|
+
if (!_instance) throw new Error("[dirk-cfx-react] createScriptConfig must be called before using ConfigPanel");
|
|
3960
3988
|
return _instance;
|
|
3961
3989
|
}
|
|
3962
|
-
function
|
|
3990
|
+
function createScriptConfig(defaultValue) {
|
|
3963
3991
|
const store = create(() => defaultValue);
|
|
3964
3992
|
let clientVersion = 0;
|
|
3965
|
-
const
|
|
3966
|
-
useNuiEvent("
|
|
3993
|
+
const useScriptConfigHooks = () => {
|
|
3994
|
+
useNuiEvent("UPDATE_SCRIPT_CONFIG", (data) => {
|
|
3967
3995
|
if (!data) return;
|
|
3968
3996
|
if (typeof data.clientVersion === "number") {
|
|
3969
3997
|
clientVersion = data.clientVersion;
|
|
3970
3998
|
}
|
|
3971
|
-
if (data.
|
|
3972
|
-
store.setState((prev) => ({ ...prev, ...data.
|
|
3999
|
+
if (data.config && typeof data.config === "object") {
|
|
4000
|
+
store.setState((prev) => ({ ...prev, ...data.config }));
|
|
3973
4001
|
}
|
|
3974
4002
|
});
|
|
3975
4003
|
};
|
|
3976
|
-
const
|
|
4004
|
+
const fetchScriptConfig = async () => {
|
|
3977
4005
|
try {
|
|
3978
|
-
const response = await fetchNui("
|
|
3979
|
-
if (response?.success && response.data?.
|
|
3980
|
-
store.setState(() => response.data.
|
|
4006
|
+
const response = await fetchNui("GET_FULL_SCRIPT_CONFIG");
|
|
4007
|
+
if (response?.success && response.data?.config) {
|
|
4008
|
+
store.setState(() => response.data.config);
|
|
3981
4009
|
if (typeof response.data.clientVersion === "number") {
|
|
3982
4010
|
clientVersion = response.data.clientVersion;
|
|
3983
4011
|
}
|
|
3984
|
-
return response.data.
|
|
4012
|
+
return response.data.config;
|
|
3985
4013
|
}
|
|
3986
4014
|
} catch {
|
|
3987
4015
|
}
|
|
3988
4016
|
return null;
|
|
3989
4017
|
};
|
|
3990
|
-
const
|
|
3991
|
-
store.setState((prev) => ({ ...prev, ...
|
|
3992
|
-
const response = await fetchNui("
|
|
3993
|
-
data:
|
|
4018
|
+
const updateScriptConfig = async (newConfig) => {
|
|
4019
|
+
store.setState((prev) => ({ ...prev, ...newConfig }));
|
|
4020
|
+
const response = await fetchNui("UPDATE_SCRIPT_CONFIG", {
|
|
4021
|
+
data: newConfig,
|
|
3994
4022
|
expectedVersion: clientVersion
|
|
3995
4023
|
});
|
|
3996
4024
|
if (response?.meta?.client_version != null) {
|
|
@@ -4001,18 +4029,29 @@ function createScriptSettings(defaultValue) {
|
|
|
4001
4029
|
}
|
|
4002
4030
|
return response;
|
|
4003
4031
|
};
|
|
4004
|
-
const
|
|
4005
|
-
return fetchNui("
|
|
4032
|
+
const getScriptConfigHistory = async (params = {}) => {
|
|
4033
|
+
return fetchNui("GET_SCRIPT_CONFIG_HISTORY", params);
|
|
4034
|
+
};
|
|
4035
|
+
const resetConfig = async () => {
|
|
4036
|
+
const response = await fetchNui("RESET_SCRIPT_CONFIG");
|
|
4037
|
+
if (response?.success) {
|
|
4038
|
+
const fresh = await fetchScriptConfig();
|
|
4039
|
+
if (fresh) {
|
|
4040
|
+
store.setState(() => fresh);
|
|
4041
|
+
}
|
|
4042
|
+
}
|
|
4043
|
+
return response;
|
|
4006
4044
|
};
|
|
4007
4045
|
_instance = {
|
|
4008
4046
|
store,
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4047
|
+
updateConfig: updateScriptConfig,
|
|
4048
|
+
resetConfig,
|
|
4049
|
+
getHistory: getScriptConfigHistory,
|
|
4050
|
+
fetchConfig: fetchScriptConfig
|
|
4012
4051
|
};
|
|
4013
|
-
return { store,
|
|
4052
|
+
return { store, updateScriptConfig, resetConfig, getScriptConfigHistory, useScriptConfigHooks, fetchScriptConfig };
|
|
4014
4053
|
}
|
|
4015
|
-
var
|
|
4054
|
+
var configPanelQueryClient = new QueryClient({
|
|
4016
4055
|
defaultOptions: { queries: { staleTime: 3e4, gcTime: 5 * 6e4 } }
|
|
4017
4056
|
});
|
|
4018
4057
|
function NavItemButton({
|
|
@@ -4056,7 +4095,7 @@ function NavItemButton({
|
|
|
4056
4095
|
}
|
|
4057
4096
|
);
|
|
4058
4097
|
}
|
|
4059
|
-
function
|
|
4098
|
+
function ConfigJsonModal({
|
|
4060
4099
|
onClose,
|
|
4061
4100
|
schema
|
|
4062
4101
|
}) {
|
|
@@ -4093,7 +4132,7 @@ function SettingsJsonModal({
|
|
|
4093
4132
|
setError(e.message);
|
|
4094
4133
|
}
|
|
4095
4134
|
};
|
|
4096
|
-
return /* @__PURE__ */ jsxs(Modal, { title: "
|
|
4135
|
+
return /* @__PURE__ */ jsxs(Modal, { title: "Config JSON", icon: Code2, iconColor: color, onClose, width: "60vh", maxHeight: "80vh", zIndex: 200, children: [
|
|
4097
4136
|
/* @__PURE__ */ jsxs(Box, { flex: 1, p: "0.8vh", style: { overflowY: "auto" }, children: [
|
|
4098
4137
|
/* @__PURE__ */ jsx(
|
|
4099
4138
|
JsonInput,
|
|
@@ -4235,10 +4274,10 @@ function HistoryTableHeader() {
|
|
|
4235
4274
|
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: "Version" })
|
|
4236
4275
|
] });
|
|
4237
4276
|
}
|
|
4238
|
-
function
|
|
4277
|
+
function ConfigHistoryModal({
|
|
4239
4278
|
onClose
|
|
4240
4279
|
}) {
|
|
4241
|
-
const { getHistory } =
|
|
4280
|
+
const { getHistory } = getScriptConfigInstance();
|
|
4242
4281
|
const theme2 = useMantineTheme();
|
|
4243
4282
|
const color = theme2.colors[theme2.primaryColor][5];
|
|
4244
4283
|
const [queryInput, setQueryInput] = useState("");
|
|
@@ -4250,7 +4289,7 @@ function SettingsHistoryModal({
|
|
|
4250
4289
|
const [expandedKey, setExpandedKey] = useState(null);
|
|
4251
4290
|
const filters = useMemo(() => ({ query, path, admin }), [query, path, admin]);
|
|
4252
4291
|
const historyQuery = useInfiniteQuery({
|
|
4253
|
-
queryKey: ["
|
|
4292
|
+
queryKey: ["scriptConfigHistory", filters],
|
|
4254
4293
|
initialPageParam: 0,
|
|
4255
4294
|
queryFn: async ({ pageParam }) => {
|
|
4256
4295
|
const response = await getHistory({
|
|
@@ -4261,7 +4300,7 @@ function SettingsHistoryModal({
|
|
|
4261
4300
|
admin: filters.admin || void 0
|
|
4262
4301
|
});
|
|
4263
4302
|
if (!response?.success || !response.data) {
|
|
4264
|
-
throw new Error(response?._error || "Failed to load
|
|
4303
|
+
throw new Error(response?._error || "Failed to load config history");
|
|
4265
4304
|
}
|
|
4266
4305
|
return response.data;
|
|
4267
4306
|
},
|
|
@@ -4275,7 +4314,7 @@ function SettingsHistoryModal({
|
|
|
4275
4314
|
historyQuery.fetchNextPage();
|
|
4276
4315
|
}
|
|
4277
4316
|
};
|
|
4278
|
-
return /* @__PURE__ */ jsxs(Modal, { title: "
|
|
4317
|
+
return /* @__PURE__ */ jsxs(Modal, { title: "Config History", icon: History, iconColor: color, onClose, width: "88vh", maxHeight: "82vh", zIndex: 260, children: [
|
|
4279
4318
|
/* @__PURE__ */ jsxs(Flex, { direction: "column", style: { flex: 1, minHeight: 0 }, children: [
|
|
4280
4319
|
/* @__PURE__ */ jsxs(Flex, { gap: "xs", p: "sm", style: { borderBottom: `0.1vh solid ${alpha(theme2.colors.dark[7], 0.8)}` }, children: [
|
|
4281
4320
|
/* @__PURE__ */ jsx(TextInput, { leftSection: /* @__PURE__ */ jsx(Search, { size: "1.4vh" }), placeholder: "Search path/admin/value", value: queryInput, onChange: (e) => setQueryInput(e.currentTarget.value), size: "xs", style: { flex: 1 } }),
|
|
@@ -4324,7 +4363,7 @@ function SettingsHistoryModal({
|
|
|
4324
4363
|
) })
|
|
4325
4364
|
] });
|
|
4326
4365
|
}
|
|
4327
|
-
function
|
|
4366
|
+
function ConfigPanelInner({
|
|
4328
4367
|
navItems,
|
|
4329
4368
|
title,
|
|
4330
4369
|
subtitle,
|
|
@@ -4333,28 +4372,37 @@ function SettingsPanelInner({
|
|
|
4333
4372
|
onClose,
|
|
4334
4373
|
schema,
|
|
4335
4374
|
resetConfirmText,
|
|
4336
|
-
|
|
4375
|
+
defaultConfig,
|
|
4337
4376
|
width,
|
|
4338
4377
|
height
|
|
4339
4378
|
}) {
|
|
4340
|
-
const {
|
|
4379
|
+
const { updateConfig, resetConfig, getHistory } = getScriptConfigInstance();
|
|
4341
4380
|
const form = useForm();
|
|
4342
4381
|
const theme2 = useMantineTheme();
|
|
4343
4382
|
const color = theme2.colors[theme2.primaryColor][5];
|
|
4344
4383
|
const version = useSettings((s) => s.resourceVersion);
|
|
4345
4384
|
const [activeTab, setActiveTab] = useState(navItems[0]?.id ?? "");
|
|
4385
|
+
const firstMountRef = useRef(true);
|
|
4346
4386
|
const [jsonOpen, setJsonOpen] = useState(false);
|
|
4347
4387
|
const [historyOpen, setHistoryOpen] = useState(false);
|
|
4348
4388
|
const [resetOpen, setResetOpen] = useState(false);
|
|
4349
|
-
const [
|
|
4389
|
+
const [pendingAction, setPendingAction] = useState(null);
|
|
4350
4390
|
const changedCount = form.changedCount ?? 0;
|
|
4351
4391
|
const isDirty = changedCount > 0;
|
|
4392
|
+
const goBack = () => fetchNui("CONFIG_PANEL_BACK");
|
|
4393
|
+
const handleBack = () => {
|
|
4394
|
+
if (isDirty) {
|
|
4395
|
+
setPendingAction("back");
|
|
4396
|
+
return;
|
|
4397
|
+
}
|
|
4398
|
+
goBack();
|
|
4399
|
+
};
|
|
4352
4400
|
useEffect(() => {
|
|
4353
4401
|
function handleKeyDown(e) {
|
|
4354
4402
|
if (e.key !== "Escape") return;
|
|
4355
4403
|
if (isDirty) {
|
|
4356
4404
|
e.preventDefault();
|
|
4357
|
-
|
|
4405
|
+
setPendingAction("close");
|
|
4358
4406
|
return;
|
|
4359
4407
|
}
|
|
4360
4408
|
onClose();
|
|
@@ -4363,34 +4411,40 @@ function SettingsPanelInner({
|
|
|
4363
4411
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4364
4412
|
}, [isDirty, onClose]);
|
|
4365
4413
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4366
|
-
/* @__PURE__ */ jsx(AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsx(
|
|
4367
|
-
/* @__PURE__ */ jsx(AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsx(
|
|
4414
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsx(ConfigJsonModal, { onClose: () => setJsonOpen(false), schema }) }),
|
|
4415
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsx(ConfigHistoryModal, { onClose: () => setHistoryOpen(false) }) }),
|
|
4368
4416
|
/* @__PURE__ */ jsx(AnimatePresence, { children: resetOpen && /* @__PURE__ */ jsx(
|
|
4369
4417
|
ConfirmModal,
|
|
4370
4418
|
{
|
|
4371
4419
|
title: "Reset to Defaults",
|
|
4372
|
-
description: "This will permanently reset ALL
|
|
4373
|
-
confirmLabel: "Reset
|
|
4420
|
+
description: "This will permanently reset ALL config back to the defaults. Every value you have configured will be overwritten. This cannot be undone.",
|
|
4421
|
+
confirmLabel: "Reset Config",
|
|
4374
4422
|
confirmText: resetConfirmText,
|
|
4375
|
-
onConfirm: () => {
|
|
4376
|
-
updateSettings(defaultSettings).then(() => form.reinitialize(cloneSettings(defaultSettings)));
|
|
4423
|
+
onConfirm: async () => {
|
|
4377
4424
|
setResetOpen(false);
|
|
4425
|
+
const result = await resetConfig();
|
|
4426
|
+
if (result?.success) {
|
|
4427
|
+
const { store } = getScriptConfigInstance();
|
|
4428
|
+
form.reinitialize(cloneConfig(store.getState()));
|
|
4429
|
+
}
|
|
4378
4430
|
},
|
|
4379
4431
|
onClose: () => setResetOpen(false),
|
|
4380
4432
|
zIndex: 300
|
|
4381
4433
|
}
|
|
4382
4434
|
) }),
|
|
4383
|
-
/* @__PURE__ */ jsx(AnimatePresence, { children:
|
|
4435
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: pendingAction !== null && /* @__PURE__ */ jsx(
|
|
4384
4436
|
ConfirmModal,
|
|
4385
4437
|
{
|
|
4386
4438
|
title: "Discard Unsaved Changes?",
|
|
4387
|
-
description: "You have unsaved changes. Closing now will discard them.",
|
|
4388
|
-
confirmLabel: "Close Without Saving",
|
|
4439
|
+
description: pendingAction === "back" ? "You have unsaved changes. Going back now will discard them." : "You have unsaved changes. Closing now will discard them.",
|
|
4440
|
+
confirmLabel: pendingAction === "back" ? "Go Back Without Saving" : "Close Without Saving",
|
|
4389
4441
|
onConfirm: () => {
|
|
4390
|
-
|
|
4391
|
-
|
|
4442
|
+
const action = pendingAction;
|
|
4443
|
+
setPendingAction(null);
|
|
4444
|
+
if (action === "back") goBack();
|
|
4445
|
+
else onClose();
|
|
4392
4446
|
},
|
|
4393
|
-
onClose: () =>
|
|
4447
|
+
onClose: () => setPendingAction(null),
|
|
4394
4448
|
zIndex: 300
|
|
4395
4449
|
}
|
|
4396
4450
|
) }),
|
|
@@ -4417,9 +4471,33 @@ function SettingsPanelInner({
|
|
|
4417
4471
|
exit: { scale: 0.3, opacity: 0, transform: "translate(-50%, -50%)" },
|
|
4418
4472
|
children: [
|
|
4419
4473
|
/* @__PURE__ */ jsxs(Flex, { direction: "column", style: { width: "18vh", flexShrink: 0, borderRight: `0.1vh solid ${alpha(theme2.colors.dark[6], 0.8)}`, background: alpha(theme2.colors.dark[8], 0.6), overflow: "hidden" }, children: [
|
|
4420
|
-
/* @__PURE__ */ jsxs(Flex, { align: "
|
|
4421
|
-
/* @__PURE__ */ jsx(
|
|
4422
|
-
|
|
4474
|
+
/* @__PURE__ */ jsxs(Flex, { align: "center", gap: "0.6vh", px: "sm", py: "sm", style: { borderBottom: `0.1vh solid ${alpha(theme2.colors.dark[6], 0.5)}`, flexShrink: 0 }, children: [
|
|
4475
|
+
/* @__PURE__ */ jsx(
|
|
4476
|
+
motion.button,
|
|
4477
|
+
{
|
|
4478
|
+
title: "Back to script list",
|
|
4479
|
+
onClick: handleBack,
|
|
4480
|
+
whileHover: { background: alpha(color, 0.16), borderColor: alpha(color, 0.45) },
|
|
4481
|
+
whileTap: { scale: 0.95 },
|
|
4482
|
+
style: {
|
|
4483
|
+
aspectRatio: "1 / 1",
|
|
4484
|
+
height: "2.4vh",
|
|
4485
|
+
background: alpha(color, 0.08),
|
|
4486
|
+
border: `0.1vh solid ${alpha(color, 0.3)}`,
|
|
4487
|
+
borderRadius: theme2.radius.xs,
|
|
4488
|
+
cursor: "pointer",
|
|
4489
|
+
display: "flex",
|
|
4490
|
+
alignItems: "center",
|
|
4491
|
+
justifyContent: "center",
|
|
4492
|
+
flexShrink: 0
|
|
4493
|
+
},
|
|
4494
|
+
children: /* @__PURE__ */ jsx(ArrowLeft, { size: "1.4vh", color })
|
|
4495
|
+
}
|
|
4496
|
+
),
|
|
4497
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", style: { minWidth: 0, lineHeight: 1 }, children: [
|
|
4498
|
+
/* @__PURE__ */ jsx(Text, { size: "lg", ff: "Akrobat Bold", tt: "uppercase", lts: "0.04em", truncate: true, children: title }),
|
|
4499
|
+
subtitle && /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.08em", c: color, truncate: true, children: subtitle })
|
|
4500
|
+
] })
|
|
4423
4501
|
] }),
|
|
4424
4502
|
/* @__PURE__ */ jsxs(Flex, { gap: "xxs", px: "xs", py: "xs", style: { borderBottom: `0.1vh solid ${alpha(theme2.colors.dark[6], 0.4)}`, flexShrink: 0 }, children: [
|
|
4425
4503
|
/* @__PURE__ */ jsx(
|
|
@@ -4522,7 +4600,7 @@ function SettingsPanelInner({
|
|
|
4522
4600
|
/* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
|
|
4523
4601
|
motion.div,
|
|
4524
4602
|
{
|
|
4525
|
-
initial: { opacity: 0, y: 4 },
|
|
4603
|
+
initial: firstMountRef.current ? (firstMountRef.current = false, false) : { opacity: 0, y: 4 },
|
|
4526
4604
|
animate: { opacity: 1, y: 0 },
|
|
4527
4605
|
exit: { opacity: 0, y: -4 },
|
|
4528
4606
|
transition: { duration: 0.15 },
|
|
@@ -4536,15 +4614,15 @@ function SettingsPanelInner({
|
|
|
4536
4614
|
)
|
|
4537
4615
|
] });
|
|
4538
4616
|
}
|
|
4539
|
-
function
|
|
4617
|
+
function cloneConfig(value) {
|
|
4540
4618
|
return JSON.parse(JSON.stringify(value));
|
|
4541
4619
|
}
|
|
4542
4620
|
function ServerOnlyFetcher() {
|
|
4543
|
-
const {
|
|
4621
|
+
const { fetchConfig } = getScriptConfigInstance();
|
|
4544
4622
|
const { reinitialize } = useFormActions();
|
|
4545
4623
|
useEffect(() => {
|
|
4546
4624
|
let cancelled = false;
|
|
4547
|
-
|
|
4625
|
+
fetchConfig().then((full) => {
|
|
4548
4626
|
if (!cancelled && full) reinitialize(full);
|
|
4549
4627
|
}).catch(() => {
|
|
4550
4628
|
});
|
|
@@ -4555,28 +4633,28 @@ function ServerOnlyFetcher() {
|
|
|
4555
4633
|
return null;
|
|
4556
4634
|
}
|
|
4557
4635
|
var defaultOnClose = () => fetchNui("CLOSE_ADMIN_SECTION");
|
|
4558
|
-
function
|
|
4636
|
+
function ConfigPanel(props) {
|
|
4559
4637
|
const { open, onClose = defaultOnClose } = props;
|
|
4560
|
-
const { store,
|
|
4638
|
+
const { store, updateConfig } = getScriptConfigInstance();
|
|
4561
4639
|
const [isSaving, setIsSaving] = useState(false);
|
|
4562
4640
|
if (!open) return null;
|
|
4563
|
-
return /* @__PURE__ */ jsx(QueryClientProvider, { client:
|
|
4641
|
+
return /* @__PURE__ */ jsx(QueryClientProvider, { client: configPanelQueryClient, children: /* @__PURE__ */ jsxs(
|
|
4564
4642
|
FormProvider,
|
|
4565
4643
|
{
|
|
4566
|
-
initialValues:
|
|
4644
|
+
initialValues: cloneConfig(store.getState()),
|
|
4567
4645
|
onSubmit: async (form) => {
|
|
4568
4646
|
if (isSaving) return;
|
|
4569
4647
|
setIsSaving(true);
|
|
4570
4648
|
try {
|
|
4571
|
-
const result = await
|
|
4649
|
+
const result = await updateConfig(form.values);
|
|
4572
4650
|
if (result?.success) {
|
|
4573
|
-
form.reinitialize(
|
|
4574
|
-
|
|
4651
|
+
form.reinitialize(cloneConfig(form.values));
|
|
4652
|
+
configPanelQueryClient.invalidateQueries({ queryKey: ["scriptConfigHistory"] });
|
|
4575
4653
|
return;
|
|
4576
4654
|
}
|
|
4577
|
-
form.reinitialize(
|
|
4655
|
+
form.reinitialize(cloneConfig(store.getState()));
|
|
4578
4656
|
if (result?._error) {
|
|
4579
|
-
console.warn(`[
|
|
4657
|
+
console.warn(`[ConfigPanel] config save failed: ${result._error}`);
|
|
4580
4658
|
}
|
|
4581
4659
|
} finally {
|
|
4582
4660
|
setIsSaving(false);
|
|
@@ -4585,7 +4663,7 @@ function SettingsPanel(props) {
|
|
|
4585
4663
|
children: [
|
|
4586
4664
|
/* @__PURE__ */ jsx(ServerOnlyFetcher, {}),
|
|
4587
4665
|
/* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(
|
|
4588
|
-
|
|
4666
|
+
ConfigPanelInner,
|
|
4589
4667
|
{
|
|
4590
4668
|
...props,
|
|
4591
4669
|
onClose,
|
|
@@ -4793,6 +4871,160 @@ function AdminPageTitle(props) {
|
|
|
4793
4871
|
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", tt: "uppercase", lts: "0.1em", size: "sm", c: "rgba(255,255,255,0.6)", children: locale(props.title) })
|
|
4794
4872
|
] });
|
|
4795
4873
|
}
|
|
4874
|
+
var loadPersistedState = (storageKey) => {
|
|
4875
|
+
try {
|
|
4876
|
+
const raw = localStorage.getItem(storageKey);
|
|
4877
|
+
return raw ? JSON.parse(raw) : {};
|
|
4878
|
+
} catch {
|
|
4879
|
+
return {};
|
|
4880
|
+
}
|
|
4881
|
+
};
|
|
4882
|
+
var savePersistedState = (storageKey, state) => {
|
|
4883
|
+
try {
|
|
4884
|
+
localStorage.setItem(storageKey, JSON.stringify(state));
|
|
4885
|
+
} catch {
|
|
4886
|
+
}
|
|
4887
|
+
};
|
|
4888
|
+
function TestBed({
|
|
4889
|
+
items,
|
|
4890
|
+
storageKey = "testbed:open-state",
|
|
4891
|
+
disablePersistence = false,
|
|
4892
|
+
title = "TestBed"
|
|
4893
|
+
}) {
|
|
4894
|
+
const [open, setOpen] = useState(false);
|
|
4895
|
+
const itemsRef = useRef(items);
|
|
4896
|
+
itemsRef.current = items;
|
|
4897
|
+
useEffect(() => {
|
|
4898
|
+
if (!isEnvBrowser() || disablePersistence) return;
|
|
4899
|
+
const persisted = loadPersistedState(storageKey);
|
|
4900
|
+
itemsRef.current.forEach((item) => {
|
|
4901
|
+
const persistedValue = persisted[item.key];
|
|
4902
|
+
if (typeof persistedValue === "boolean" && persistedValue !== item.active) {
|
|
4903
|
+
item.onToggle(persistedValue);
|
|
4904
|
+
}
|
|
4905
|
+
});
|
|
4906
|
+
}, []);
|
|
4907
|
+
if (!isEnvBrowser()) return null;
|
|
4908
|
+
const toggle = (item) => {
|
|
4909
|
+
const next = !item.active;
|
|
4910
|
+
item.onToggle(next);
|
|
4911
|
+
if (!disablePersistence) {
|
|
4912
|
+
const persisted = loadPersistedState(storageKey);
|
|
4913
|
+
persisted[item.key] = next;
|
|
4914
|
+
savePersistedState(storageKey, persisted);
|
|
4915
|
+
}
|
|
4916
|
+
};
|
|
4917
|
+
return /* @__PURE__ */ jsxs(
|
|
4918
|
+
"div",
|
|
4919
|
+
{
|
|
4920
|
+
style: {
|
|
4921
|
+
position: "fixed",
|
|
4922
|
+
top: "1vh",
|
|
4923
|
+
left: "1vh",
|
|
4924
|
+
zIndex: 2147483647,
|
|
4925
|
+
pointerEvents: "auto",
|
|
4926
|
+
fontSize: "1.4vh"
|
|
4927
|
+
},
|
|
4928
|
+
children: [
|
|
4929
|
+
/* @__PURE__ */ jsxs(
|
|
4930
|
+
Flex,
|
|
4931
|
+
{
|
|
4932
|
+
align: "center",
|
|
4933
|
+
gap: "xs",
|
|
4934
|
+
px: "sm",
|
|
4935
|
+
py: "xs",
|
|
4936
|
+
onClick: () => setOpen((v) => !v),
|
|
4937
|
+
style: {
|
|
4938
|
+
cursor: "pointer",
|
|
4939
|
+
background: "rgba(0,0,0,0.55)",
|
|
4940
|
+
backdropFilter: "blur(0.6vh)",
|
|
4941
|
+
WebkitBackdropFilter: "blur(0.6vh)",
|
|
4942
|
+
border: "0.1vh solid rgba(255,255,255,0.1)",
|
|
4943
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
4944
|
+
userSelect: "none",
|
|
4945
|
+
minWidth: "16vh"
|
|
4946
|
+
},
|
|
4947
|
+
children: [
|
|
4948
|
+
/* @__PURE__ */ jsx(FlaskConical, { size: 14, color: "rgba(255,255,255,0.7)" }),
|
|
4949
|
+
/* @__PURE__ */ jsx(
|
|
4950
|
+
Text,
|
|
4951
|
+
{
|
|
4952
|
+
size: "xs",
|
|
4953
|
+
ff: "Akrobat Bold",
|
|
4954
|
+
tt: "uppercase",
|
|
4955
|
+
lts: "0.08em",
|
|
4956
|
+
c: "rgba(255,255,255,0.85)",
|
|
4957
|
+
style: { flex: 1 },
|
|
4958
|
+
children: title
|
|
4959
|
+
}
|
|
4960
|
+
),
|
|
4961
|
+
/* @__PURE__ */ jsx(ActionIcon, { size: "xs", variant: "transparent", c: "rgba(255,255,255,0.6)", children: open ? /* @__PURE__ */ jsx(ChevronUp, { size: 14 }) : /* @__PURE__ */ jsx(ChevronDown, { size: 14 }) })
|
|
4962
|
+
]
|
|
4963
|
+
}
|
|
4964
|
+
),
|
|
4965
|
+
open && /* @__PURE__ */ jsx(
|
|
4966
|
+
Stack,
|
|
4967
|
+
{
|
|
4968
|
+
gap: 4,
|
|
4969
|
+
mt: "xxs",
|
|
4970
|
+
p: "xs",
|
|
4971
|
+
style: {
|
|
4972
|
+
background: "rgba(0,0,0,0.55)",
|
|
4973
|
+
backdropFilter: "blur(0.6vh)",
|
|
4974
|
+
WebkitBackdropFilter: "blur(0.6vh)",
|
|
4975
|
+
border: "0.1vh solid rgba(255,255,255,0.1)",
|
|
4976
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
4977
|
+
minWidth: "16vh",
|
|
4978
|
+
maxHeight: "80vh",
|
|
4979
|
+
overflowY: "auto"
|
|
4980
|
+
},
|
|
4981
|
+
children: items.map((item) => /* @__PURE__ */ jsxs(
|
|
4982
|
+
Flex,
|
|
4983
|
+
{
|
|
4984
|
+
align: "center",
|
|
4985
|
+
justify: "space-between",
|
|
4986
|
+
gap: "xs",
|
|
4987
|
+
px: "xs",
|
|
4988
|
+
py: "xxs",
|
|
4989
|
+
onClick: () => toggle(item),
|
|
4990
|
+
style: {
|
|
4991
|
+
cursor: "pointer",
|
|
4992
|
+
borderRadius: "var(--mantine-radius-xs)",
|
|
4993
|
+
background: item.active ? "rgba(245,158,11,0.15)" : "rgba(255,255,255,0.03)",
|
|
4994
|
+
border: `0.1vh solid ${item.active ? "rgba(245,158,11,0.35)" : "rgba(255,255,255,0.05)"}`,
|
|
4995
|
+
userSelect: "none"
|
|
4996
|
+
},
|
|
4997
|
+
children: [
|
|
4998
|
+
/* @__PURE__ */ jsx(
|
|
4999
|
+
Text,
|
|
5000
|
+
{
|
|
5001
|
+
size: "xs",
|
|
5002
|
+
ff: "Akrobat Bold",
|
|
5003
|
+
c: item.active ? "#f59e0b" : "rgba(255,255,255,0.75)",
|
|
5004
|
+
children: item.label
|
|
5005
|
+
}
|
|
5006
|
+
),
|
|
5007
|
+
/* @__PURE__ */ jsx(
|
|
5008
|
+
Text,
|
|
5009
|
+
{
|
|
5010
|
+
size: "xxs",
|
|
5011
|
+
ff: "Akrobat Bold",
|
|
5012
|
+
tt: "uppercase",
|
|
5013
|
+
lts: "0.06em",
|
|
5014
|
+
c: item.active ? "#f59e0b" : "rgba(255,255,255,0.35)",
|
|
5015
|
+
children: item.active ? "On" : "Off"
|
|
5016
|
+
}
|
|
5017
|
+
)
|
|
5018
|
+
]
|
|
5019
|
+
},
|
|
5020
|
+
item.key
|
|
5021
|
+
))
|
|
5022
|
+
}
|
|
5023
|
+
)
|
|
5024
|
+
]
|
|
5025
|
+
}
|
|
5026
|
+
);
|
|
5027
|
+
}
|
|
4796
5028
|
function useTornEdges() {
|
|
4797
5029
|
const game = useSettings((state) => state.game);
|
|
4798
5030
|
return game === "rdr3" ? "torn-edge-wrapper" : "";
|
|
@@ -4973,6 +5205,11 @@ function mergeMantineThemeSafe(base, custom, override) {
|
|
|
4973
5205
|
const colors = { ...base.colors };
|
|
4974
5206
|
if (custom && isValidColorScale(custom)) {
|
|
4975
5207
|
colors["custom"] = custom;
|
|
5208
|
+
} else if (!colors["custom"]) {
|
|
5209
|
+
const fallback = base.colors && base.colors.dirk;
|
|
5210
|
+
if (fallback && isValidColorScale(fallback)) {
|
|
5211
|
+
colors["custom"] = fallback;
|
|
5212
|
+
}
|
|
4976
5213
|
}
|
|
4977
5214
|
return {
|
|
4978
5215
|
...base,
|
|
@@ -5046,6 +5283,7 @@ function DirkProvider({ children, overideResourceName, themeOverride }) {
|
|
|
5046
5283
|
customTheme,
|
|
5047
5284
|
game
|
|
5048
5285
|
} = useSettings();
|
|
5286
|
+
localeStore((s) => s.locales);
|
|
5049
5287
|
useLayoutEffect(() => {
|
|
5050
5288
|
useSettings.setState({
|
|
5051
5289
|
overideResourceName
|
|
@@ -5066,6 +5304,10 @@ function DirkProvider({ children, overideResourceName, themeOverride }) {
|
|
|
5066
5304
|
console.error("Failed to fetch initial settings within dirk-cfx-react:", err);
|
|
5067
5305
|
});
|
|
5068
5306
|
}, []);
|
|
5307
|
+
useNuiEvent("UPDATE_DIRK_LIB_SETTINGS", (data) => {
|
|
5308
|
+
if (!data || typeof data !== "object") return;
|
|
5309
|
+
useSettings.setState(data);
|
|
5310
|
+
});
|
|
5069
5311
|
const mergedTheme = useMemo(
|
|
5070
5312
|
() => mergeMantineThemeSafe(
|
|
5071
5313
|
{ ...theme_default, primaryColor, primaryShade },
|
|
@@ -5089,6 +5331,6 @@ function DirkProvider({ children, overideResourceName, themeOverride }) {
|
|
|
5089
5331
|
return /* @__PURE__ */ jsx(MantineProvider, { theme: mergedTheme, defaultColorScheme: "dark", children: /* @__PURE__ */ jsx(DirkErrorBoundary, { children: content }) });
|
|
5090
5332
|
}
|
|
5091
5333
|
|
|
5092
|
-
export { AdminPageTitle, AsyncSaveButton, BlipColorSelect, BlipIconSelect, BorderedIcon, ConfirmModal, Counter, DirkProvider, FiveMKeyBindInput, FloatingParticles, FormProvider, INPUT_MAPPER_KEYS_BY_PRIMARY, INPUT_MAPPER_PRIMARY_OPTIONS, InfoBox, InputContainer, LevelBanner, LevelPanel, Modal, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PromptModal, SegmentedControl, SegmentedProgress, SelectItem,
|
|
5334
|
+
export { AdminPageTitle, AsyncSaveButton, BlipColorSelect, BlipIconSelect, BorderedIcon, ConfigPanel, ConfirmModal, Counter, DirkProvider, FiveMKeyBindInput, FloatingParticles, FormProvider, INPUT_MAPPER_KEYS_BY_PRIMARY, INPUT_MAPPER_PRIMARY_OPTIONS, InfoBox, InputContainer, LevelBanner, LevelPanel, Modal, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PromptModal, SegmentedControl, SegmentedProgress, SelectItem, TestBed, Title, TornEdgeSVGFilter, colorWithAlpha, copyToClipboard, createFormStore, createScriptConfig, createSkill, extractDefaults, fetchLuaTable, fetchNui, gameToMap, getImageShape, getItemImageUrl, getScriptConfigInstance, initialFetches, internalEvent, isEnvBrowser, isProfanity, latPr100, locale, localeStore, mapCenter, mapToGame, noop, numberToRoman, openLink, registerInitialFetch, registerInitialLuaTableFetch, runFetches, splitFAString, updatePresignedURL, uploadImage, useAudio, useAutoFetcher, useForm, useFormActions, useFormError, useFormErrors, useFormField, useFormFields, useItems, useItemsList, useModal, useModalActions, useNavigation, useNavigationStore, useNuiEvent, useProfanityStore, useSettings, useTornEdges };
|
|
5093
5335
|
//# sourceMappingURL=index.js.map
|
|
5094
5336
|
//# sourceMappingURL=index.js.map
|