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/components/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { Flex, Text, Image, TextInput, Select, Box, useMantineTheme, alpha, Progress, RingProgress, Portal, Button, Loader, Group, JsonInput } from '@mantine/core';
|
|
1
|
+
import { Flex, Text, Image, TextInput, Select, Box, useMantineTheme, Tooltip, alpha, Progress, RingProgress, Portal, Button, Loader, ActionIcon, Stack, Group, JsonInput } from '@mantine/core';
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import { createContext, useContext, useRef, useState, useEffect, useMemo } from 'react';
|
|
4
4
|
import { create, useStore, createStore } from 'zustand';
|
|
5
5
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
6
6
|
import { motion, AnimatePresence, useMotionValue } from 'framer-motion';
|
|
7
|
+
import { Info, X, AlertTriangle, Trash2, Check, FlaskConical, ChevronUp, ChevronDown, ArrowLeft, Undo2, Redo2, Save, History, XCircle, Code2, RotateCcw, Search, Filter, User } from 'lucide-react';
|
|
7
8
|
import clickSoundUrl from '../click_sound-PNCRRTM4.mp3';
|
|
8
9
|
import hoverSoundUrl from '../hover_sound-NBUA222C.mp3';
|
|
9
|
-
import { X, AlertTriangle, Trash2, Check, Undo2, Redo2, Save, History, XCircle, Code2, RotateCcw, Search, Filter, User, ChevronDown } from 'lucide-react';
|
|
10
10
|
import { QueryClient, QueryClientProvider, useInfiniteQuery } from '@tanstack/react-query';
|
|
11
11
|
|
|
12
12
|
// src/components/BlipSelect.tsx
|
|
@@ -1267,13 +1267,24 @@ async function fetchNui(eventName, data, mockData) {
|
|
|
1267
1267
|
}
|
|
1268
1268
|
const overrideResourceName = useSettings.getState().overideResourceName;
|
|
1269
1269
|
const resourceName = window.GetParentResourceName ? window.GetParentResourceName() : overrideResourceName ? overrideResourceName : "dirk-cfx-react";
|
|
1270
|
-
|
|
1271
|
-
|
|
1270
|
+
try {
|
|
1271
|
+
const resp = await fetch(`https://${resourceName}/${eventName}`, options);
|
|
1272
|
+
return await resp.json();
|
|
1273
|
+
} catch {
|
|
1274
|
+
return mockData ?? {};
|
|
1275
|
+
}
|
|
1272
1276
|
}
|
|
1273
1277
|
async function registerInitialFetch(eventName, data, mockData) {
|
|
1274
1278
|
const fetcher = () => fetchNui(eventName, data, mockData);
|
|
1275
1279
|
return fetcher();
|
|
1276
1280
|
}
|
|
1281
|
+
var reportedMissing = /* @__PURE__ */ new Set();
|
|
1282
|
+
function reportMissingLocale(key) {
|
|
1283
|
+
if (!key || reportedMissing.has(key)) return;
|
|
1284
|
+
reportedMissing.add(key);
|
|
1285
|
+
fetchNui("REPORT_MISSING_LOCALE", { key }).catch(() => {
|
|
1286
|
+
});
|
|
1287
|
+
}
|
|
1277
1288
|
var localeStore = create((set, get) => {
|
|
1278
1289
|
return {
|
|
1279
1290
|
locales: {
|
|
@@ -1281,6 +1292,7 @@ var localeStore = create((set, get) => {
|
|
|
1281
1292
|
},
|
|
1282
1293
|
locale: (key, ...args) => {
|
|
1283
1294
|
const exists = get().locales[key];
|
|
1295
|
+
if (!exists) reportMissingLocale(key);
|
|
1284
1296
|
let translation = exists || key;
|
|
1285
1297
|
if (args.length) {
|
|
1286
1298
|
translation = translation.replace(/%s/g, () => String(args.shift() || ""));
|
|
@@ -1292,7 +1304,16 @@ var localeStore = create((set, get) => {
|
|
|
1292
1304
|
var locale = localeStore.getState().locale;
|
|
1293
1305
|
registerInitialFetch("GET_LOCALES", void 0).then((data) => {
|
|
1294
1306
|
localeStore.setState({ locales: data });
|
|
1307
|
+
}).catch(() => {
|
|
1295
1308
|
});
|
|
1309
|
+
if (typeof window !== "undefined") {
|
|
1310
|
+
window.addEventListener("message", (event) => {
|
|
1311
|
+
const msg = event.data;
|
|
1312
|
+
if (!msg || msg.action !== "UPDATE_DIRK_LIB_LOCALES") return;
|
|
1313
|
+
if (!msg.data || typeof msg.data !== "object") return;
|
|
1314
|
+
localeStore.setState({ locales: msg.data });
|
|
1315
|
+
});
|
|
1316
|
+
}
|
|
1296
1317
|
var useItems = create(() => ({}));
|
|
1297
1318
|
var useItemsList = (excludeItemNames = []) => {
|
|
1298
1319
|
const excludeSet = new Set(excludeItemNames);
|
|
@@ -1305,6 +1326,7 @@ registerInitialFetch("FETCH_ALL_ITEMS", null, {
|
|
|
1305
1326
|
}).then((fetchedItems) => {
|
|
1306
1327
|
if (!fetchedItems) return;
|
|
1307
1328
|
useItems.setState(fetchedItems);
|
|
1329
|
+
}).catch(() => {
|
|
1308
1330
|
});
|
|
1309
1331
|
|
|
1310
1332
|
// src/utils/inputMapper.ts
|
|
@@ -1931,8 +1953,8 @@ function InputContainer(props) {
|
|
|
1931
1953
|
(props.title || props.description) && /* @__PURE__ */ jsxs(
|
|
1932
1954
|
Flex,
|
|
1933
1955
|
{
|
|
1934
|
-
|
|
1935
|
-
|
|
1956
|
+
align: "center",
|
|
1957
|
+
flex: 1,
|
|
1936
1958
|
p: props.p == "0" ? "sm" : 0,
|
|
1937
1959
|
children: [
|
|
1938
1960
|
props.title && /* @__PURE__ */ jsx(
|
|
@@ -1949,12 +1971,26 @@ function InputContainer(props) {
|
|
|
1949
1971
|
}
|
|
1950
1972
|
),
|
|
1951
1973
|
props.description && /* @__PURE__ */ jsx(
|
|
1952
|
-
|
|
1974
|
+
Tooltip,
|
|
1953
1975
|
{
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1976
|
+
label: props.description,
|
|
1977
|
+
position: "top-end",
|
|
1978
|
+
withArrow: true,
|
|
1979
|
+
multiline: true,
|
|
1980
|
+
maw: "22vh",
|
|
1981
|
+
styles: {
|
|
1982
|
+
tooltip: {
|
|
1983
|
+
background: alpha(theme.colors.dark[7], 0.95),
|
|
1984
|
+
border: `0.1vh solid rgba(255,255,255,0.1)`,
|
|
1985
|
+
color: "rgba(255,255,255,0.75)",
|
|
1986
|
+
fontFamily: "Akrobat Bold",
|
|
1987
|
+
fontSize: "1.3vh",
|
|
1988
|
+
lineHeight: 1.3,
|
|
1989
|
+
padding: "0.6vh 0.8vh",
|
|
1990
|
+
letterSpacing: "0.03em"
|
|
1991
|
+
}
|
|
1992
|
+
},
|
|
1993
|
+
children: /* @__PURE__ */ jsx(Flex, { align: "center", justify: "center", style: { marginLeft: "auto", cursor: "help" }, children: /* @__PURE__ */ jsx(Info, { size: "1.6vh", color: alpha(theme.colors[theme.primaryColor][5], 0.45) }) })
|
|
1958
1994
|
}
|
|
1959
1995
|
)
|
|
1960
1996
|
]
|
|
@@ -1971,13 +2007,7 @@ function InputContainer(props) {
|
|
|
1971
2007
|
children: props.error
|
|
1972
2008
|
}
|
|
1973
2009
|
),
|
|
1974
|
-
/* @__PURE__ */ jsx(
|
|
1975
|
-
Flex,
|
|
1976
|
-
{
|
|
1977
|
-
ml: "auto",
|
|
1978
|
-
children: props.rightSection
|
|
1979
|
-
}
|
|
1980
|
-
)
|
|
2010
|
+
props.rightSection && /* @__PURE__ */ jsx(Flex, { children: props.rightSection })
|
|
1981
2011
|
]
|
|
1982
2012
|
}
|
|
1983
2013
|
),
|
|
@@ -2668,7 +2698,7 @@ function Modal({
|
|
|
2668
2698
|
children: description
|
|
2669
2699
|
}
|
|
2670
2700
|
) }),
|
|
2671
|
-
children
|
|
2701
|
+
/* @__PURE__ */ jsx("div", { style: { flex: 1, minHeight: 0, display: "flex", flexDirection: "column" }, children })
|
|
2672
2702
|
]
|
|
2673
2703
|
}
|
|
2674
2704
|
)
|
|
@@ -3291,10 +3321,10 @@ function useFormActions() {
|
|
|
3291
3321
|
}
|
|
3292
3322
|
return store.getState();
|
|
3293
3323
|
}
|
|
3294
|
-
function
|
|
3295
|
-
throw new Error("[dirk-cfx-react]
|
|
3324
|
+
function getScriptConfigInstance() {
|
|
3325
|
+
throw new Error("[dirk-cfx-react] createScriptConfig must be called before using ConfigPanel");
|
|
3296
3326
|
}
|
|
3297
|
-
var
|
|
3327
|
+
var configPanelQueryClient = new QueryClient({
|
|
3298
3328
|
defaultOptions: { queries: { staleTime: 3e4, gcTime: 5 * 6e4 } }
|
|
3299
3329
|
});
|
|
3300
3330
|
function NavItemButton({
|
|
@@ -3338,7 +3368,7 @@ function NavItemButton({
|
|
|
3338
3368
|
}
|
|
3339
3369
|
);
|
|
3340
3370
|
}
|
|
3341
|
-
function
|
|
3371
|
+
function ConfigJsonModal({
|
|
3342
3372
|
onClose,
|
|
3343
3373
|
schema
|
|
3344
3374
|
}) {
|
|
@@ -3375,7 +3405,7 @@ function SettingsJsonModal({
|
|
|
3375
3405
|
setError(e.message);
|
|
3376
3406
|
}
|
|
3377
3407
|
};
|
|
3378
|
-
return /* @__PURE__ */ jsxs(Modal, { title: "
|
|
3408
|
+
return /* @__PURE__ */ jsxs(Modal, { title: "Config JSON", icon: Code2, iconColor: color, onClose, width: "60vh", maxHeight: "80vh", zIndex: 200, children: [
|
|
3379
3409
|
/* @__PURE__ */ jsxs(Box, { flex: 1, p: "0.8vh", style: { overflowY: "auto" }, children: [
|
|
3380
3410
|
/* @__PURE__ */ jsx(
|
|
3381
3411
|
JsonInput,
|
|
@@ -3517,10 +3547,10 @@ function HistoryTableHeader() {
|
|
|
3517
3547
|
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: "Version" })
|
|
3518
3548
|
] });
|
|
3519
3549
|
}
|
|
3520
|
-
function
|
|
3550
|
+
function ConfigHistoryModal({
|
|
3521
3551
|
onClose
|
|
3522
3552
|
}) {
|
|
3523
|
-
const { getHistory } =
|
|
3553
|
+
const { getHistory } = getScriptConfigInstance();
|
|
3524
3554
|
const theme = useMantineTheme();
|
|
3525
3555
|
const color = theme.colors[theme.primaryColor][5];
|
|
3526
3556
|
const [queryInput, setQueryInput] = useState("");
|
|
@@ -3532,7 +3562,7 @@ function SettingsHistoryModal({
|
|
|
3532
3562
|
const [expandedKey, setExpandedKey] = useState(null);
|
|
3533
3563
|
const filters = useMemo(() => ({ query, path, admin }), [query, path, admin]);
|
|
3534
3564
|
const historyQuery = useInfiniteQuery({
|
|
3535
|
-
queryKey: ["
|
|
3565
|
+
queryKey: ["scriptConfigHistory", filters],
|
|
3536
3566
|
initialPageParam: 0,
|
|
3537
3567
|
queryFn: async ({ pageParam }) => {
|
|
3538
3568
|
const response = await getHistory({
|
|
@@ -3543,7 +3573,7 @@ function SettingsHistoryModal({
|
|
|
3543
3573
|
admin: filters.admin || void 0
|
|
3544
3574
|
});
|
|
3545
3575
|
if (!response?.success || !response.data) {
|
|
3546
|
-
throw new Error(response?._error || "Failed to load
|
|
3576
|
+
throw new Error(response?._error || "Failed to load config history");
|
|
3547
3577
|
}
|
|
3548
3578
|
return response.data;
|
|
3549
3579
|
},
|
|
@@ -3557,7 +3587,7 @@ function SettingsHistoryModal({
|
|
|
3557
3587
|
historyQuery.fetchNextPage();
|
|
3558
3588
|
}
|
|
3559
3589
|
};
|
|
3560
|
-
return /* @__PURE__ */ jsxs(Modal, { title: "
|
|
3590
|
+
return /* @__PURE__ */ jsxs(Modal, { title: "Config History", icon: History, iconColor: color, onClose, width: "88vh", maxHeight: "82vh", zIndex: 260, children: [
|
|
3561
3591
|
/* @__PURE__ */ jsxs(Flex, { direction: "column", style: { flex: 1, minHeight: 0 }, children: [
|
|
3562
3592
|
/* @__PURE__ */ jsxs(Flex, { gap: "xs", p: "sm", style: { borderBottom: `0.1vh solid ${alpha(theme.colors.dark[7], 0.8)}` }, children: [
|
|
3563
3593
|
/* @__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 } }),
|
|
@@ -3606,7 +3636,7 @@ function SettingsHistoryModal({
|
|
|
3606
3636
|
) })
|
|
3607
3637
|
] });
|
|
3608
3638
|
}
|
|
3609
|
-
function
|
|
3639
|
+
function ConfigPanelInner({
|
|
3610
3640
|
navItems,
|
|
3611
3641
|
title,
|
|
3612
3642
|
subtitle,
|
|
@@ -3615,28 +3645,37 @@ function SettingsPanelInner({
|
|
|
3615
3645
|
onClose,
|
|
3616
3646
|
schema,
|
|
3617
3647
|
resetConfirmText,
|
|
3618
|
-
|
|
3648
|
+
defaultConfig,
|
|
3619
3649
|
width,
|
|
3620
3650
|
height
|
|
3621
3651
|
}) {
|
|
3622
|
-
const {
|
|
3652
|
+
const { updateConfig, resetConfig, getHistory } = getScriptConfigInstance();
|
|
3623
3653
|
const form = useForm();
|
|
3624
3654
|
const theme = useMantineTheme();
|
|
3625
3655
|
const color = theme.colors[theme.primaryColor][5];
|
|
3626
3656
|
const version = useSettings((s) => s.resourceVersion);
|
|
3627
3657
|
const [activeTab, setActiveTab] = useState(navItems[0]?.id ?? "");
|
|
3658
|
+
const firstMountRef = useRef(true);
|
|
3628
3659
|
const [jsonOpen, setJsonOpen] = useState(false);
|
|
3629
3660
|
const [historyOpen, setHistoryOpen] = useState(false);
|
|
3630
3661
|
const [resetOpen, setResetOpen] = useState(false);
|
|
3631
|
-
const [
|
|
3662
|
+
const [pendingAction, setPendingAction] = useState(null);
|
|
3632
3663
|
const changedCount = form.changedCount ?? 0;
|
|
3633
3664
|
const isDirty = changedCount > 0;
|
|
3665
|
+
const goBack = () => fetchNui("CONFIG_PANEL_BACK");
|
|
3666
|
+
const handleBack = () => {
|
|
3667
|
+
if (isDirty) {
|
|
3668
|
+
setPendingAction("back");
|
|
3669
|
+
return;
|
|
3670
|
+
}
|
|
3671
|
+
goBack();
|
|
3672
|
+
};
|
|
3634
3673
|
useEffect(() => {
|
|
3635
3674
|
function handleKeyDown(e) {
|
|
3636
3675
|
if (e.key !== "Escape") return;
|
|
3637
3676
|
if (isDirty) {
|
|
3638
3677
|
e.preventDefault();
|
|
3639
|
-
|
|
3678
|
+
setPendingAction("close");
|
|
3640
3679
|
return;
|
|
3641
3680
|
}
|
|
3642
3681
|
onClose();
|
|
@@ -3645,34 +3684,40 @@ function SettingsPanelInner({
|
|
|
3645
3684
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
3646
3685
|
}, [isDirty, onClose]);
|
|
3647
3686
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3648
|
-
/* @__PURE__ */ jsx(AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsx(
|
|
3649
|
-
/* @__PURE__ */ jsx(AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsx(
|
|
3687
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsx(ConfigJsonModal, { onClose: () => setJsonOpen(false), schema }) }),
|
|
3688
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsx(ConfigHistoryModal, { onClose: () => setHistoryOpen(false) }) }),
|
|
3650
3689
|
/* @__PURE__ */ jsx(AnimatePresence, { children: resetOpen && /* @__PURE__ */ jsx(
|
|
3651
3690
|
ConfirmModal,
|
|
3652
3691
|
{
|
|
3653
3692
|
title: "Reset to Defaults",
|
|
3654
|
-
description: "This will permanently reset ALL
|
|
3655
|
-
confirmLabel: "Reset
|
|
3693
|
+
description: "This will permanently reset ALL config back to the defaults. Every value you have configured will be overwritten. This cannot be undone.",
|
|
3694
|
+
confirmLabel: "Reset Config",
|
|
3656
3695
|
confirmText: resetConfirmText,
|
|
3657
|
-
onConfirm: () => {
|
|
3658
|
-
updateSettings(defaultSettings).then(() => form.reinitialize(cloneSettings(defaultSettings)));
|
|
3696
|
+
onConfirm: async () => {
|
|
3659
3697
|
setResetOpen(false);
|
|
3698
|
+
const result = await resetConfig();
|
|
3699
|
+
if (result?.success) {
|
|
3700
|
+
const { store } = getScriptConfigInstance();
|
|
3701
|
+
form.reinitialize(cloneConfig(store.getState()));
|
|
3702
|
+
}
|
|
3660
3703
|
},
|
|
3661
3704
|
onClose: () => setResetOpen(false),
|
|
3662
3705
|
zIndex: 300
|
|
3663
3706
|
}
|
|
3664
3707
|
) }),
|
|
3665
|
-
/* @__PURE__ */ jsx(AnimatePresence, { children:
|
|
3708
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: pendingAction !== null && /* @__PURE__ */ jsx(
|
|
3666
3709
|
ConfirmModal,
|
|
3667
3710
|
{
|
|
3668
3711
|
title: "Discard Unsaved Changes?",
|
|
3669
|
-
description: "You have unsaved changes. Closing now will discard them.",
|
|
3670
|
-
confirmLabel: "Close Without Saving",
|
|
3712
|
+
description: pendingAction === "back" ? "You have unsaved changes. Going back now will discard them." : "You have unsaved changes. Closing now will discard them.",
|
|
3713
|
+
confirmLabel: pendingAction === "back" ? "Go Back Without Saving" : "Close Without Saving",
|
|
3671
3714
|
onConfirm: () => {
|
|
3672
|
-
|
|
3673
|
-
|
|
3715
|
+
const action = pendingAction;
|
|
3716
|
+
setPendingAction(null);
|
|
3717
|
+
if (action === "back") goBack();
|
|
3718
|
+
else onClose();
|
|
3674
3719
|
},
|
|
3675
|
-
onClose: () =>
|
|
3720
|
+
onClose: () => setPendingAction(null),
|
|
3676
3721
|
zIndex: 300
|
|
3677
3722
|
}
|
|
3678
3723
|
) }),
|
|
@@ -3699,9 +3744,33 @@ function SettingsPanelInner({
|
|
|
3699
3744
|
exit: { scale: 0.3, opacity: 0, transform: "translate(-50%, -50%)" },
|
|
3700
3745
|
children: [
|
|
3701
3746
|
/* @__PURE__ */ jsxs(Flex, { direction: "column", style: { width: "18vh", flexShrink: 0, borderRight: `0.1vh solid ${alpha(theme.colors.dark[6], 0.8)}`, background: alpha(theme.colors.dark[8], 0.6), overflow: "hidden" }, children: [
|
|
3702
|
-
/* @__PURE__ */ jsxs(Flex, { align: "
|
|
3703
|
-
/* @__PURE__ */ jsx(
|
|
3704
|
-
|
|
3747
|
+
/* @__PURE__ */ jsxs(Flex, { align: "center", gap: "0.6vh", px: "sm", py: "sm", style: { borderBottom: `0.1vh solid ${alpha(theme.colors.dark[6], 0.5)}`, flexShrink: 0 }, children: [
|
|
3748
|
+
/* @__PURE__ */ jsx(
|
|
3749
|
+
motion.button,
|
|
3750
|
+
{
|
|
3751
|
+
title: "Back to script list",
|
|
3752
|
+
onClick: handleBack,
|
|
3753
|
+
whileHover: { background: alpha(color, 0.16), borderColor: alpha(color, 0.45) },
|
|
3754
|
+
whileTap: { scale: 0.95 },
|
|
3755
|
+
style: {
|
|
3756
|
+
aspectRatio: "1 / 1",
|
|
3757
|
+
height: "2.4vh",
|
|
3758
|
+
background: alpha(color, 0.08),
|
|
3759
|
+
border: `0.1vh solid ${alpha(color, 0.3)}`,
|
|
3760
|
+
borderRadius: theme.radius.xs,
|
|
3761
|
+
cursor: "pointer",
|
|
3762
|
+
display: "flex",
|
|
3763
|
+
alignItems: "center",
|
|
3764
|
+
justifyContent: "center",
|
|
3765
|
+
flexShrink: 0
|
|
3766
|
+
},
|
|
3767
|
+
children: /* @__PURE__ */ jsx(ArrowLeft, { size: "1.4vh", color })
|
|
3768
|
+
}
|
|
3769
|
+
),
|
|
3770
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", style: { minWidth: 0, lineHeight: 1 }, children: [
|
|
3771
|
+
/* @__PURE__ */ jsx(Text, { size: "lg", ff: "Akrobat Bold", tt: "uppercase", lts: "0.04em", truncate: true, children: title }),
|
|
3772
|
+
subtitle && /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.08em", c: color, truncate: true, children: subtitle })
|
|
3773
|
+
] })
|
|
3705
3774
|
] }),
|
|
3706
3775
|
/* @__PURE__ */ jsxs(Flex, { gap: "xxs", px: "xs", py: "xs", style: { borderBottom: `0.1vh solid ${alpha(theme.colors.dark[6], 0.4)}`, flexShrink: 0 }, children: [
|
|
3707
3776
|
/* @__PURE__ */ jsx(
|
|
@@ -3804,7 +3873,7 @@ function SettingsPanelInner({
|
|
|
3804
3873
|
/* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
|
|
3805
3874
|
motion.div,
|
|
3806
3875
|
{
|
|
3807
|
-
initial: { opacity: 0, y: 4 },
|
|
3876
|
+
initial: firstMountRef.current ? (firstMountRef.current = false, false) : { opacity: 0, y: 4 },
|
|
3808
3877
|
animate: { opacity: 1, y: 0 },
|
|
3809
3878
|
exit: { opacity: 0, y: -4 },
|
|
3810
3879
|
transition: { duration: 0.15 },
|
|
@@ -3818,15 +3887,15 @@ function SettingsPanelInner({
|
|
|
3818
3887
|
)
|
|
3819
3888
|
] });
|
|
3820
3889
|
}
|
|
3821
|
-
function
|
|
3890
|
+
function cloneConfig(value) {
|
|
3822
3891
|
return JSON.parse(JSON.stringify(value));
|
|
3823
3892
|
}
|
|
3824
3893
|
function ServerOnlyFetcher() {
|
|
3825
|
-
const {
|
|
3894
|
+
const { fetchConfig } = getScriptConfigInstance();
|
|
3826
3895
|
const { reinitialize } = useFormActions();
|
|
3827
3896
|
useEffect(() => {
|
|
3828
3897
|
let cancelled = false;
|
|
3829
|
-
|
|
3898
|
+
fetchConfig().then((full) => {
|
|
3830
3899
|
if (!cancelled && full) reinitialize(full);
|
|
3831
3900
|
}).catch(() => {
|
|
3832
3901
|
});
|
|
@@ -3837,28 +3906,28 @@ function ServerOnlyFetcher() {
|
|
|
3837
3906
|
return null;
|
|
3838
3907
|
}
|
|
3839
3908
|
var defaultOnClose = () => fetchNui("CLOSE_ADMIN_SECTION");
|
|
3840
|
-
function
|
|
3909
|
+
function ConfigPanel(props) {
|
|
3841
3910
|
const { open, onClose = defaultOnClose } = props;
|
|
3842
|
-
const { store,
|
|
3911
|
+
const { store, updateConfig } = getScriptConfigInstance();
|
|
3843
3912
|
const [isSaving, setIsSaving] = useState(false);
|
|
3844
3913
|
if (!open) return null;
|
|
3845
|
-
return /* @__PURE__ */ jsx(QueryClientProvider, { client:
|
|
3914
|
+
return /* @__PURE__ */ jsx(QueryClientProvider, { client: configPanelQueryClient, children: /* @__PURE__ */ jsxs(
|
|
3846
3915
|
FormProvider,
|
|
3847
3916
|
{
|
|
3848
|
-
initialValues:
|
|
3917
|
+
initialValues: cloneConfig(store.getState()),
|
|
3849
3918
|
onSubmit: async (form) => {
|
|
3850
3919
|
if (isSaving) return;
|
|
3851
3920
|
setIsSaving(true);
|
|
3852
3921
|
try {
|
|
3853
|
-
const result = await
|
|
3922
|
+
const result = await updateConfig(form.values);
|
|
3854
3923
|
if (result?.success) {
|
|
3855
|
-
form.reinitialize(
|
|
3856
|
-
|
|
3924
|
+
form.reinitialize(cloneConfig(form.values));
|
|
3925
|
+
configPanelQueryClient.invalidateQueries({ queryKey: ["scriptConfigHistory"] });
|
|
3857
3926
|
return;
|
|
3858
3927
|
}
|
|
3859
|
-
form.reinitialize(
|
|
3928
|
+
form.reinitialize(cloneConfig(store.getState()));
|
|
3860
3929
|
if (result?._error) {
|
|
3861
|
-
console.warn(`[
|
|
3930
|
+
console.warn(`[ConfigPanel] config save failed: ${result._error}`);
|
|
3862
3931
|
}
|
|
3863
3932
|
} finally {
|
|
3864
3933
|
setIsSaving(false);
|
|
@@ -3867,7 +3936,7 @@ function SettingsPanel(props) {
|
|
|
3867
3936
|
children: [
|
|
3868
3937
|
/* @__PURE__ */ jsx(ServerOnlyFetcher, {}),
|
|
3869
3938
|
/* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(
|
|
3870
|
-
|
|
3939
|
+
ConfigPanelInner,
|
|
3871
3940
|
{
|
|
3872
3941
|
...props,
|
|
3873
3942
|
onClose,
|
|
@@ -4075,7 +4144,161 @@ function AdminPageTitle(props) {
|
|
|
4075
4144
|
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", tt: "uppercase", lts: "0.1em", size: "sm", c: "rgba(255,255,255,0.6)", children: locale(props.title) })
|
|
4076
4145
|
] });
|
|
4077
4146
|
}
|
|
4147
|
+
var loadPersistedState = (storageKey) => {
|
|
4148
|
+
try {
|
|
4149
|
+
const raw = localStorage.getItem(storageKey);
|
|
4150
|
+
return raw ? JSON.parse(raw) : {};
|
|
4151
|
+
} catch {
|
|
4152
|
+
return {};
|
|
4153
|
+
}
|
|
4154
|
+
};
|
|
4155
|
+
var savePersistedState = (storageKey, state) => {
|
|
4156
|
+
try {
|
|
4157
|
+
localStorage.setItem(storageKey, JSON.stringify(state));
|
|
4158
|
+
} catch {
|
|
4159
|
+
}
|
|
4160
|
+
};
|
|
4161
|
+
function TestBed({
|
|
4162
|
+
items,
|
|
4163
|
+
storageKey = "testbed:open-state",
|
|
4164
|
+
disablePersistence = false,
|
|
4165
|
+
title = "TestBed"
|
|
4166
|
+
}) {
|
|
4167
|
+
const [open, setOpen] = useState(false);
|
|
4168
|
+
const itemsRef = useRef(items);
|
|
4169
|
+
itemsRef.current = items;
|
|
4170
|
+
useEffect(() => {
|
|
4171
|
+
if (!isEnvBrowser() || disablePersistence) return;
|
|
4172
|
+
const persisted = loadPersistedState(storageKey);
|
|
4173
|
+
itemsRef.current.forEach((item) => {
|
|
4174
|
+
const persistedValue = persisted[item.key];
|
|
4175
|
+
if (typeof persistedValue === "boolean" && persistedValue !== item.active) {
|
|
4176
|
+
item.onToggle(persistedValue);
|
|
4177
|
+
}
|
|
4178
|
+
});
|
|
4179
|
+
}, []);
|
|
4180
|
+
if (!isEnvBrowser()) return null;
|
|
4181
|
+
const toggle = (item) => {
|
|
4182
|
+
const next = !item.active;
|
|
4183
|
+
item.onToggle(next);
|
|
4184
|
+
if (!disablePersistence) {
|
|
4185
|
+
const persisted = loadPersistedState(storageKey);
|
|
4186
|
+
persisted[item.key] = next;
|
|
4187
|
+
savePersistedState(storageKey, persisted);
|
|
4188
|
+
}
|
|
4189
|
+
};
|
|
4190
|
+
return /* @__PURE__ */ jsxs(
|
|
4191
|
+
"div",
|
|
4192
|
+
{
|
|
4193
|
+
style: {
|
|
4194
|
+
position: "fixed",
|
|
4195
|
+
top: "1vh",
|
|
4196
|
+
left: "1vh",
|
|
4197
|
+
zIndex: 2147483647,
|
|
4198
|
+
pointerEvents: "auto",
|
|
4199
|
+
fontSize: "1.4vh"
|
|
4200
|
+
},
|
|
4201
|
+
children: [
|
|
4202
|
+
/* @__PURE__ */ jsxs(
|
|
4203
|
+
Flex,
|
|
4204
|
+
{
|
|
4205
|
+
align: "center",
|
|
4206
|
+
gap: "xs",
|
|
4207
|
+
px: "sm",
|
|
4208
|
+
py: "xs",
|
|
4209
|
+
onClick: () => setOpen((v) => !v),
|
|
4210
|
+
style: {
|
|
4211
|
+
cursor: "pointer",
|
|
4212
|
+
background: "rgba(0,0,0,0.55)",
|
|
4213
|
+
backdropFilter: "blur(0.6vh)",
|
|
4214
|
+
WebkitBackdropFilter: "blur(0.6vh)",
|
|
4215
|
+
border: "0.1vh solid rgba(255,255,255,0.1)",
|
|
4216
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
4217
|
+
userSelect: "none",
|
|
4218
|
+
minWidth: "16vh"
|
|
4219
|
+
},
|
|
4220
|
+
children: [
|
|
4221
|
+
/* @__PURE__ */ jsx(FlaskConical, { size: 14, color: "rgba(255,255,255,0.7)" }),
|
|
4222
|
+
/* @__PURE__ */ jsx(
|
|
4223
|
+
Text,
|
|
4224
|
+
{
|
|
4225
|
+
size: "xs",
|
|
4226
|
+
ff: "Akrobat Bold",
|
|
4227
|
+
tt: "uppercase",
|
|
4228
|
+
lts: "0.08em",
|
|
4229
|
+
c: "rgba(255,255,255,0.85)",
|
|
4230
|
+
style: { flex: 1 },
|
|
4231
|
+
children: title
|
|
4232
|
+
}
|
|
4233
|
+
),
|
|
4234
|
+
/* @__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 }) })
|
|
4235
|
+
]
|
|
4236
|
+
}
|
|
4237
|
+
),
|
|
4238
|
+
open && /* @__PURE__ */ jsx(
|
|
4239
|
+
Stack,
|
|
4240
|
+
{
|
|
4241
|
+
gap: 4,
|
|
4242
|
+
mt: "xxs",
|
|
4243
|
+
p: "xs",
|
|
4244
|
+
style: {
|
|
4245
|
+
background: "rgba(0,0,0,0.55)",
|
|
4246
|
+
backdropFilter: "blur(0.6vh)",
|
|
4247
|
+
WebkitBackdropFilter: "blur(0.6vh)",
|
|
4248
|
+
border: "0.1vh solid rgba(255,255,255,0.1)",
|
|
4249
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
4250
|
+
minWidth: "16vh",
|
|
4251
|
+
maxHeight: "80vh",
|
|
4252
|
+
overflowY: "auto"
|
|
4253
|
+
},
|
|
4254
|
+
children: items.map((item) => /* @__PURE__ */ jsxs(
|
|
4255
|
+
Flex,
|
|
4256
|
+
{
|
|
4257
|
+
align: "center",
|
|
4258
|
+
justify: "space-between",
|
|
4259
|
+
gap: "xs",
|
|
4260
|
+
px: "xs",
|
|
4261
|
+
py: "xxs",
|
|
4262
|
+
onClick: () => toggle(item),
|
|
4263
|
+
style: {
|
|
4264
|
+
cursor: "pointer",
|
|
4265
|
+
borderRadius: "var(--mantine-radius-xs)",
|
|
4266
|
+
background: item.active ? "rgba(245,158,11,0.15)" : "rgba(255,255,255,0.03)",
|
|
4267
|
+
border: `0.1vh solid ${item.active ? "rgba(245,158,11,0.35)" : "rgba(255,255,255,0.05)"}`,
|
|
4268
|
+
userSelect: "none"
|
|
4269
|
+
},
|
|
4270
|
+
children: [
|
|
4271
|
+
/* @__PURE__ */ jsx(
|
|
4272
|
+
Text,
|
|
4273
|
+
{
|
|
4274
|
+
size: "xs",
|
|
4275
|
+
ff: "Akrobat Bold",
|
|
4276
|
+
c: item.active ? "#f59e0b" : "rgba(255,255,255,0.75)",
|
|
4277
|
+
children: item.label
|
|
4278
|
+
}
|
|
4279
|
+
),
|
|
4280
|
+
/* @__PURE__ */ jsx(
|
|
4281
|
+
Text,
|
|
4282
|
+
{
|
|
4283
|
+
size: "xxs",
|
|
4284
|
+
ff: "Akrobat Bold",
|
|
4285
|
+
tt: "uppercase",
|
|
4286
|
+
lts: "0.06em",
|
|
4287
|
+
c: item.active ? "#f59e0b" : "rgba(255,255,255,0.35)",
|
|
4288
|
+
children: item.active ? "On" : "Off"
|
|
4289
|
+
}
|
|
4290
|
+
)
|
|
4291
|
+
]
|
|
4292
|
+
},
|
|
4293
|
+
item.key
|
|
4294
|
+
))
|
|
4295
|
+
}
|
|
4296
|
+
)
|
|
4297
|
+
]
|
|
4298
|
+
}
|
|
4299
|
+
);
|
|
4300
|
+
}
|
|
4078
4301
|
|
|
4079
|
-
export { AdminPageTitle, AsyncSaveButton, BlipColorSelect, BlipIconSelect, BorderedIcon, ConfirmModal, Counter, FiveMKeyBindInput, FloatingParticles, InfoBox, InputContainer, LevelBanner, LevelPanel, Modal, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PromptModal, SegmentedControl, SegmentedProgress, SelectItem,
|
|
4302
|
+
export { AdminPageTitle, AsyncSaveButton, BlipColorSelect, BlipIconSelect, BorderedIcon, ConfigPanel, ConfirmModal, Counter, FiveMKeyBindInput, FloatingParticles, InfoBox, InputContainer, LevelBanner, LevelPanel, Modal, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PromptModal, SegmentedControl, SegmentedProgress, SelectItem, TestBed, Title, useModal, useModalActions, useNavigation, useNavigationStore };
|
|
4080
4303
|
//# sourceMappingURL=index.js.map
|
|
4081
4304
|
//# sourceMappingURL=index.js.map
|