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
|
@@ -6,9 +6,9 @@ var react = require('react');
|
|
|
6
6
|
var zustand = require('zustand');
|
|
7
7
|
var reactFontawesome = require('@fortawesome/react-fontawesome');
|
|
8
8
|
var framerMotion = require('framer-motion');
|
|
9
|
+
var lucideReact = require('lucide-react');
|
|
9
10
|
var clickSoundUrl = require('../click_sound-PNCRRTM4.mp3');
|
|
10
11
|
var hoverSoundUrl = require('../hover_sound-NBUA222C.mp3');
|
|
11
|
-
var lucideReact = require('lucide-react');
|
|
12
12
|
var reactQuery = require('@tanstack/react-query');
|
|
13
13
|
|
|
14
14
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -1274,13 +1274,24 @@ async function fetchNui(eventName, data, mockData) {
|
|
|
1274
1274
|
}
|
|
1275
1275
|
const overrideResourceName = useSettings.getState().overideResourceName;
|
|
1276
1276
|
const resourceName = window.GetParentResourceName ? window.GetParentResourceName() : overrideResourceName ? overrideResourceName : "dirk-cfx-react";
|
|
1277
|
-
|
|
1278
|
-
|
|
1277
|
+
try {
|
|
1278
|
+
const resp = await fetch(`https://${resourceName}/${eventName}`, options);
|
|
1279
|
+
return await resp.json();
|
|
1280
|
+
} catch {
|
|
1281
|
+
return mockData ?? {};
|
|
1282
|
+
}
|
|
1279
1283
|
}
|
|
1280
1284
|
async function registerInitialFetch(eventName, data, mockData) {
|
|
1281
1285
|
const fetcher = () => fetchNui(eventName, data, mockData);
|
|
1282
1286
|
return fetcher();
|
|
1283
1287
|
}
|
|
1288
|
+
var reportedMissing = /* @__PURE__ */ new Set();
|
|
1289
|
+
function reportMissingLocale(key) {
|
|
1290
|
+
if (!key || reportedMissing.has(key)) return;
|
|
1291
|
+
reportedMissing.add(key);
|
|
1292
|
+
fetchNui("REPORT_MISSING_LOCALE", { key }).catch(() => {
|
|
1293
|
+
});
|
|
1294
|
+
}
|
|
1284
1295
|
var localeStore = zustand.create((set, get) => {
|
|
1285
1296
|
return {
|
|
1286
1297
|
locales: {
|
|
@@ -1288,6 +1299,7 @@ var localeStore = zustand.create((set, get) => {
|
|
|
1288
1299
|
},
|
|
1289
1300
|
locale: (key, ...args) => {
|
|
1290
1301
|
const exists = get().locales[key];
|
|
1302
|
+
if (!exists) reportMissingLocale(key);
|
|
1291
1303
|
let translation = exists || key;
|
|
1292
1304
|
if (args.length) {
|
|
1293
1305
|
translation = translation.replace(/%s/g, () => String(args.shift() || ""));
|
|
@@ -1299,7 +1311,16 @@ var localeStore = zustand.create((set, get) => {
|
|
|
1299
1311
|
var locale = localeStore.getState().locale;
|
|
1300
1312
|
registerInitialFetch("GET_LOCALES", void 0).then((data) => {
|
|
1301
1313
|
localeStore.setState({ locales: data });
|
|
1314
|
+
}).catch(() => {
|
|
1302
1315
|
});
|
|
1316
|
+
if (typeof window !== "undefined") {
|
|
1317
|
+
window.addEventListener("message", (event) => {
|
|
1318
|
+
const msg = event.data;
|
|
1319
|
+
if (!msg || msg.action !== "UPDATE_DIRK_LIB_LOCALES") return;
|
|
1320
|
+
if (!msg.data || typeof msg.data !== "object") return;
|
|
1321
|
+
localeStore.setState({ locales: msg.data });
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1303
1324
|
var useItems = zustand.create(() => ({}));
|
|
1304
1325
|
var useItemsList = (excludeItemNames = []) => {
|
|
1305
1326
|
const excludeSet = new Set(excludeItemNames);
|
|
@@ -1312,6 +1333,7 @@ registerInitialFetch("FETCH_ALL_ITEMS", null, {
|
|
|
1312
1333
|
}).then((fetchedItems) => {
|
|
1313
1334
|
if (!fetchedItems) return;
|
|
1314
1335
|
useItems.setState(fetchedItems);
|
|
1336
|
+
}).catch(() => {
|
|
1315
1337
|
});
|
|
1316
1338
|
|
|
1317
1339
|
// src/utils/inputMapper.ts
|
|
@@ -1938,8 +1960,8 @@ function InputContainer(props) {
|
|
|
1938
1960
|
(props.title || props.description) && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1939
1961
|
core.Flex,
|
|
1940
1962
|
{
|
|
1941
|
-
|
|
1942
|
-
|
|
1963
|
+
align: "center",
|
|
1964
|
+
flex: 1,
|
|
1943
1965
|
p: props.p == "0" ? "sm" : 0,
|
|
1944
1966
|
children: [
|
|
1945
1967
|
props.title && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1956,12 +1978,26 @@ function InputContainer(props) {
|
|
|
1956
1978
|
}
|
|
1957
1979
|
),
|
|
1958
1980
|
props.description && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1959
|
-
core.
|
|
1981
|
+
core.Tooltip,
|
|
1960
1982
|
{
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1983
|
+
label: props.description,
|
|
1984
|
+
position: "top-end",
|
|
1985
|
+
withArrow: true,
|
|
1986
|
+
multiline: true,
|
|
1987
|
+
maw: "22vh",
|
|
1988
|
+
styles: {
|
|
1989
|
+
tooltip: {
|
|
1990
|
+
background: core.alpha(theme.colors.dark[7], 0.95),
|
|
1991
|
+
border: `0.1vh solid rgba(255,255,255,0.1)`,
|
|
1992
|
+
color: "rgba(255,255,255,0.75)",
|
|
1993
|
+
fontFamily: "Akrobat Bold",
|
|
1994
|
+
fontSize: "1.3vh",
|
|
1995
|
+
lineHeight: 1.3,
|
|
1996
|
+
padding: "0.6vh 0.8vh",
|
|
1997
|
+
letterSpacing: "0.03em"
|
|
1998
|
+
}
|
|
1999
|
+
},
|
|
2000
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(core.Flex, { align: "center", justify: "center", style: { marginLeft: "auto", cursor: "help" }, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { size: "1.6vh", color: core.alpha(theme.colors[theme.primaryColor][5], 0.45) }) })
|
|
1965
2001
|
}
|
|
1966
2002
|
)
|
|
1967
2003
|
]
|
|
@@ -1978,13 +2014,7 @@ function InputContainer(props) {
|
|
|
1978
2014
|
children: props.error
|
|
1979
2015
|
}
|
|
1980
2016
|
),
|
|
1981
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1982
|
-
core.Flex,
|
|
1983
|
-
{
|
|
1984
|
-
ml: "auto",
|
|
1985
|
-
children: props.rightSection
|
|
1986
|
-
}
|
|
1987
|
-
)
|
|
2017
|
+
props.rightSection && /* @__PURE__ */ jsxRuntime.jsx(core.Flex, { children: props.rightSection })
|
|
1988
2018
|
]
|
|
1989
2019
|
}
|
|
1990
2020
|
),
|
|
@@ -2675,7 +2705,7 @@ function Modal({
|
|
|
2675
2705
|
children: description
|
|
2676
2706
|
}
|
|
2677
2707
|
) }),
|
|
2678
|
-
children
|
|
2708
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, minHeight: 0, display: "flex", flexDirection: "column" }, children })
|
|
2679
2709
|
]
|
|
2680
2710
|
}
|
|
2681
2711
|
)
|
|
@@ -3298,10 +3328,10 @@ function useFormActions() {
|
|
|
3298
3328
|
}
|
|
3299
3329
|
return store.getState();
|
|
3300
3330
|
}
|
|
3301
|
-
function
|
|
3302
|
-
throw new Error("[dirk-cfx-react]
|
|
3331
|
+
function getScriptConfigInstance() {
|
|
3332
|
+
throw new Error("[dirk-cfx-react] createScriptConfig must be called before using ConfigPanel");
|
|
3303
3333
|
}
|
|
3304
|
-
var
|
|
3334
|
+
var configPanelQueryClient = new reactQuery.QueryClient({
|
|
3305
3335
|
defaultOptions: { queries: { staleTime: 3e4, gcTime: 5 * 6e4 } }
|
|
3306
3336
|
});
|
|
3307
3337
|
function NavItemButton({
|
|
@@ -3345,7 +3375,7 @@ function NavItemButton({
|
|
|
3345
3375
|
}
|
|
3346
3376
|
);
|
|
3347
3377
|
}
|
|
3348
|
-
function
|
|
3378
|
+
function ConfigJsonModal({
|
|
3349
3379
|
onClose,
|
|
3350
3380
|
schema
|
|
3351
3381
|
}) {
|
|
@@ -3382,7 +3412,7 @@ function SettingsJsonModal({
|
|
|
3382
3412
|
setError(e.message);
|
|
3383
3413
|
}
|
|
3384
3414
|
};
|
|
3385
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "
|
|
3415
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "Config JSON", icon: lucideReact.Code2, iconColor: color, onClose, width: "60vh", maxHeight: "80vh", zIndex: 200, children: [
|
|
3386
3416
|
/* @__PURE__ */ jsxRuntime.jsxs(core.Box, { flex: 1, p: "0.8vh", style: { overflowY: "auto" }, children: [
|
|
3387
3417
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3388
3418
|
core.JsonInput,
|
|
@@ -3524,10 +3554,10 @@ function HistoryTableHeader() {
|
|
|
3524
3554
|
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: "Version" })
|
|
3525
3555
|
] });
|
|
3526
3556
|
}
|
|
3527
|
-
function
|
|
3557
|
+
function ConfigHistoryModal({
|
|
3528
3558
|
onClose
|
|
3529
3559
|
}) {
|
|
3530
|
-
const { getHistory } =
|
|
3560
|
+
const { getHistory } = getScriptConfigInstance();
|
|
3531
3561
|
const theme = core.useMantineTheme();
|
|
3532
3562
|
const color = theme.colors[theme.primaryColor][5];
|
|
3533
3563
|
const [queryInput, setQueryInput] = react.useState("");
|
|
@@ -3539,7 +3569,7 @@ function SettingsHistoryModal({
|
|
|
3539
3569
|
const [expandedKey, setExpandedKey] = react.useState(null);
|
|
3540
3570
|
const filters = react.useMemo(() => ({ query, path, admin }), [query, path, admin]);
|
|
3541
3571
|
const historyQuery = reactQuery.useInfiniteQuery({
|
|
3542
|
-
queryKey: ["
|
|
3572
|
+
queryKey: ["scriptConfigHistory", filters],
|
|
3543
3573
|
initialPageParam: 0,
|
|
3544
3574
|
queryFn: async ({ pageParam }) => {
|
|
3545
3575
|
const response = await getHistory({
|
|
@@ -3550,7 +3580,7 @@ function SettingsHistoryModal({
|
|
|
3550
3580
|
admin: filters.admin || void 0
|
|
3551
3581
|
});
|
|
3552
3582
|
if (!response?.success || !response.data) {
|
|
3553
|
-
throw new Error(response?._error || "Failed to load
|
|
3583
|
+
throw new Error(response?._error || "Failed to load config history");
|
|
3554
3584
|
}
|
|
3555
3585
|
return response.data;
|
|
3556
3586
|
},
|
|
@@ -3564,7 +3594,7 @@ function SettingsHistoryModal({
|
|
|
3564
3594
|
historyQuery.fetchNextPage();
|
|
3565
3595
|
}
|
|
3566
3596
|
};
|
|
3567
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "
|
|
3597
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "Config History", icon: lucideReact.History, iconColor: color, onClose, width: "88vh", maxHeight: "82vh", zIndex: 260, children: [
|
|
3568
3598
|
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { flex: 1, minHeight: 0 }, children: [
|
|
3569
3599
|
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { gap: "xs", p: "sm", style: { borderBottom: `0.1vh solid ${core.alpha(theme.colors.dark[7], 0.8)}` }, children: [
|
|
3570
3600
|
/* @__PURE__ */ jsxRuntime.jsx(core.TextInput, { leftSection: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { size: "1.4vh" }), placeholder: "Search path/admin/value", value: queryInput, onChange: (e) => setQueryInput(e.currentTarget.value), size: "xs", style: { flex: 1 } }),
|
|
@@ -3613,7 +3643,7 @@ function SettingsHistoryModal({
|
|
|
3613
3643
|
) })
|
|
3614
3644
|
] });
|
|
3615
3645
|
}
|
|
3616
|
-
function
|
|
3646
|
+
function ConfigPanelInner({
|
|
3617
3647
|
navItems,
|
|
3618
3648
|
title,
|
|
3619
3649
|
subtitle,
|
|
@@ -3622,28 +3652,37 @@ function SettingsPanelInner({
|
|
|
3622
3652
|
onClose,
|
|
3623
3653
|
schema,
|
|
3624
3654
|
resetConfirmText,
|
|
3625
|
-
|
|
3655
|
+
defaultConfig,
|
|
3626
3656
|
width,
|
|
3627
3657
|
height
|
|
3628
3658
|
}) {
|
|
3629
|
-
const {
|
|
3659
|
+
const { updateConfig, resetConfig, getHistory } = getScriptConfigInstance();
|
|
3630
3660
|
const form = useForm();
|
|
3631
3661
|
const theme = core.useMantineTheme();
|
|
3632
3662
|
const color = theme.colors[theme.primaryColor][5];
|
|
3633
3663
|
const version = useSettings((s) => s.resourceVersion);
|
|
3634
3664
|
const [activeTab, setActiveTab] = react.useState(navItems[0]?.id ?? "");
|
|
3665
|
+
const firstMountRef = react.useRef(true);
|
|
3635
3666
|
const [jsonOpen, setJsonOpen] = react.useState(false);
|
|
3636
3667
|
const [historyOpen, setHistoryOpen] = react.useState(false);
|
|
3637
3668
|
const [resetOpen, setResetOpen] = react.useState(false);
|
|
3638
|
-
const [
|
|
3669
|
+
const [pendingAction, setPendingAction] = react.useState(null);
|
|
3639
3670
|
const changedCount = form.changedCount ?? 0;
|
|
3640
3671
|
const isDirty = changedCount > 0;
|
|
3672
|
+
const goBack = () => fetchNui("CONFIG_PANEL_BACK");
|
|
3673
|
+
const handleBack = () => {
|
|
3674
|
+
if (isDirty) {
|
|
3675
|
+
setPendingAction("back");
|
|
3676
|
+
return;
|
|
3677
|
+
}
|
|
3678
|
+
goBack();
|
|
3679
|
+
};
|
|
3641
3680
|
react.useEffect(() => {
|
|
3642
3681
|
function handleKeyDown(e) {
|
|
3643
3682
|
if (e.key !== "Escape") return;
|
|
3644
3683
|
if (isDirty) {
|
|
3645
3684
|
e.preventDefault();
|
|
3646
|
-
|
|
3685
|
+
setPendingAction("close");
|
|
3647
3686
|
return;
|
|
3648
3687
|
}
|
|
3649
3688
|
onClose();
|
|
@@ -3652,34 +3691,40 @@ function SettingsPanelInner({
|
|
|
3652
3691
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
3653
3692
|
}, [isDirty, onClose]);
|
|
3654
3693
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3655
|
-
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3656
|
-
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3694
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsxRuntime.jsx(ConfigJsonModal, { onClose: () => setJsonOpen(false), schema }) }),
|
|
3695
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsxRuntime.jsx(ConfigHistoryModal, { onClose: () => setHistoryOpen(false) }) }),
|
|
3657
3696
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: resetOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3658
3697
|
ConfirmModal,
|
|
3659
3698
|
{
|
|
3660
3699
|
title: "Reset to Defaults",
|
|
3661
|
-
description: "This will permanently reset ALL
|
|
3662
|
-
confirmLabel: "Reset
|
|
3700
|
+
description: "This will permanently reset ALL config back to the defaults. Every value you have configured will be overwritten. This cannot be undone.",
|
|
3701
|
+
confirmLabel: "Reset Config",
|
|
3663
3702
|
confirmText: resetConfirmText,
|
|
3664
|
-
onConfirm: () => {
|
|
3665
|
-
updateSettings(defaultSettings).then(() => form.reinitialize(cloneSettings(defaultSettings)));
|
|
3703
|
+
onConfirm: async () => {
|
|
3666
3704
|
setResetOpen(false);
|
|
3705
|
+
const result = await resetConfig();
|
|
3706
|
+
if (result?.success) {
|
|
3707
|
+
const { store } = getScriptConfigInstance();
|
|
3708
|
+
form.reinitialize(cloneConfig(store.getState()));
|
|
3709
|
+
}
|
|
3667
3710
|
},
|
|
3668
3711
|
onClose: () => setResetOpen(false),
|
|
3669
3712
|
zIndex: 300
|
|
3670
3713
|
}
|
|
3671
3714
|
) }),
|
|
3672
|
-
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children:
|
|
3715
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: pendingAction !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3673
3716
|
ConfirmModal,
|
|
3674
3717
|
{
|
|
3675
3718
|
title: "Discard Unsaved Changes?",
|
|
3676
|
-
description: "You have unsaved changes. Closing now will discard them.",
|
|
3677
|
-
confirmLabel: "Close Without Saving",
|
|
3719
|
+
description: pendingAction === "back" ? "You have unsaved changes. Going back now will discard them." : "You have unsaved changes. Closing now will discard them.",
|
|
3720
|
+
confirmLabel: pendingAction === "back" ? "Go Back Without Saving" : "Close Without Saving",
|
|
3678
3721
|
onConfirm: () => {
|
|
3679
|
-
|
|
3680
|
-
|
|
3722
|
+
const action = pendingAction;
|
|
3723
|
+
setPendingAction(null);
|
|
3724
|
+
if (action === "back") goBack();
|
|
3725
|
+
else onClose();
|
|
3681
3726
|
},
|
|
3682
|
-
onClose: () =>
|
|
3727
|
+
onClose: () => setPendingAction(null),
|
|
3683
3728
|
zIndex: 300
|
|
3684
3729
|
}
|
|
3685
3730
|
) }),
|
|
@@ -3706,9 +3751,33 @@ function SettingsPanelInner({
|
|
|
3706
3751
|
exit: { scale: 0.3, opacity: 0, transform: "translate(-50%, -50%)" },
|
|
3707
3752
|
children: [
|
|
3708
3753
|
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { width: "18vh", flexShrink: 0, borderRight: `0.1vh solid ${core.alpha(theme.colors.dark[6], 0.8)}`, background: core.alpha(theme.colors.dark[8], 0.6), overflow: "hidden" }, children: [
|
|
3709
|
-
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "
|
|
3710
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3711
|
-
|
|
3754
|
+
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "0.6vh", px: "sm", py: "sm", style: { borderBottom: `0.1vh solid ${core.alpha(theme.colors.dark[6], 0.5)}`, flexShrink: 0 }, children: [
|
|
3755
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3756
|
+
framerMotion.motion.button,
|
|
3757
|
+
{
|
|
3758
|
+
title: "Back to script list",
|
|
3759
|
+
onClick: handleBack,
|
|
3760
|
+
whileHover: { background: core.alpha(color, 0.16), borderColor: core.alpha(color, 0.45) },
|
|
3761
|
+
whileTap: { scale: 0.95 },
|
|
3762
|
+
style: {
|
|
3763
|
+
aspectRatio: "1 / 1",
|
|
3764
|
+
height: "2.4vh",
|
|
3765
|
+
background: core.alpha(color, 0.08),
|
|
3766
|
+
border: `0.1vh solid ${core.alpha(color, 0.3)}`,
|
|
3767
|
+
borderRadius: theme.radius.xs,
|
|
3768
|
+
cursor: "pointer",
|
|
3769
|
+
display: "flex",
|
|
3770
|
+
alignItems: "center",
|
|
3771
|
+
justifyContent: "center",
|
|
3772
|
+
flexShrink: 0
|
|
3773
|
+
},
|
|
3774
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { size: "1.4vh", color })
|
|
3775
|
+
}
|
|
3776
|
+
),
|
|
3777
|
+
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { minWidth: 0, lineHeight: 1 }, children: [
|
|
3778
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { size: "lg", ff: "Akrobat Bold", tt: "uppercase", lts: "0.04em", truncate: true, children: title }),
|
|
3779
|
+
subtitle && /* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.08em", c: color, truncate: true, children: subtitle })
|
|
3780
|
+
] })
|
|
3712
3781
|
] }),
|
|
3713
3782
|
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { gap: "xxs", px: "xs", py: "xs", style: { borderBottom: `0.1vh solid ${core.alpha(theme.colors.dark[6], 0.4)}`, flexShrink: 0 }, children: [
|
|
3714
3783
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3811,7 +3880,7 @@ function SettingsPanelInner({
|
|
|
3811
3880
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3812
3881
|
framerMotion.motion.div,
|
|
3813
3882
|
{
|
|
3814
|
-
initial: { opacity: 0, y: 4 },
|
|
3883
|
+
initial: firstMountRef.current ? (firstMountRef.current = false, false) : { opacity: 0, y: 4 },
|
|
3815
3884
|
animate: { opacity: 1, y: 0 },
|
|
3816
3885
|
exit: { opacity: 0, y: -4 },
|
|
3817
3886
|
transition: { duration: 0.15 },
|
|
@@ -3825,15 +3894,15 @@ function SettingsPanelInner({
|
|
|
3825
3894
|
)
|
|
3826
3895
|
] });
|
|
3827
3896
|
}
|
|
3828
|
-
function
|
|
3897
|
+
function cloneConfig(value) {
|
|
3829
3898
|
return JSON.parse(JSON.stringify(value));
|
|
3830
3899
|
}
|
|
3831
3900
|
function ServerOnlyFetcher() {
|
|
3832
|
-
const {
|
|
3901
|
+
const { fetchConfig } = getScriptConfigInstance();
|
|
3833
3902
|
const { reinitialize } = useFormActions();
|
|
3834
3903
|
react.useEffect(() => {
|
|
3835
3904
|
let cancelled = false;
|
|
3836
|
-
|
|
3905
|
+
fetchConfig().then((full) => {
|
|
3837
3906
|
if (!cancelled && full) reinitialize(full);
|
|
3838
3907
|
}).catch(() => {
|
|
3839
3908
|
});
|
|
@@ -3844,28 +3913,28 @@ function ServerOnlyFetcher() {
|
|
|
3844
3913
|
return null;
|
|
3845
3914
|
}
|
|
3846
3915
|
var defaultOnClose = () => fetchNui("CLOSE_ADMIN_SECTION");
|
|
3847
|
-
function
|
|
3916
|
+
function ConfigPanel(props) {
|
|
3848
3917
|
const { open, onClose = defaultOnClose } = props;
|
|
3849
|
-
const { store,
|
|
3918
|
+
const { store, updateConfig } = getScriptConfigInstance();
|
|
3850
3919
|
const [isSaving, setIsSaving] = react.useState(false);
|
|
3851
3920
|
if (!open) return null;
|
|
3852
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client:
|
|
3921
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: configPanelQueryClient, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3853
3922
|
FormProvider,
|
|
3854
3923
|
{
|
|
3855
|
-
initialValues:
|
|
3924
|
+
initialValues: cloneConfig(store.getState()),
|
|
3856
3925
|
onSubmit: async (form) => {
|
|
3857
3926
|
if (isSaving) return;
|
|
3858
3927
|
setIsSaving(true);
|
|
3859
3928
|
try {
|
|
3860
|
-
const result = await
|
|
3929
|
+
const result = await updateConfig(form.values);
|
|
3861
3930
|
if (result?.success) {
|
|
3862
|
-
form.reinitialize(
|
|
3863
|
-
|
|
3931
|
+
form.reinitialize(cloneConfig(form.values));
|
|
3932
|
+
configPanelQueryClient.invalidateQueries({ queryKey: ["scriptConfigHistory"] });
|
|
3864
3933
|
return;
|
|
3865
3934
|
}
|
|
3866
|
-
form.reinitialize(
|
|
3935
|
+
form.reinitialize(cloneConfig(store.getState()));
|
|
3867
3936
|
if (result?._error) {
|
|
3868
|
-
console.warn(`[
|
|
3937
|
+
console.warn(`[ConfigPanel] config save failed: ${result._error}`);
|
|
3869
3938
|
}
|
|
3870
3939
|
} finally {
|
|
3871
3940
|
setIsSaving(false);
|
|
@@ -3874,7 +3943,7 @@ function SettingsPanel(props) {
|
|
|
3874
3943
|
children: [
|
|
3875
3944
|
/* @__PURE__ */ jsxRuntime.jsx(ServerOnlyFetcher, {}),
|
|
3876
3945
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3877
|
-
|
|
3946
|
+
ConfigPanelInner,
|
|
3878
3947
|
{
|
|
3879
3948
|
...props,
|
|
3880
3949
|
onClose,
|
|
@@ -4082,12 +4151,167 @@ function AdminPageTitle(props) {
|
|
|
4082
4151
|
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", tt: "uppercase", lts: "0.1em", size: "sm", c: "rgba(255,255,255,0.6)", children: locale(props.title) })
|
|
4083
4152
|
] });
|
|
4084
4153
|
}
|
|
4154
|
+
var loadPersistedState = (storageKey) => {
|
|
4155
|
+
try {
|
|
4156
|
+
const raw = localStorage.getItem(storageKey);
|
|
4157
|
+
return raw ? JSON.parse(raw) : {};
|
|
4158
|
+
} catch {
|
|
4159
|
+
return {};
|
|
4160
|
+
}
|
|
4161
|
+
};
|
|
4162
|
+
var savePersistedState = (storageKey, state) => {
|
|
4163
|
+
try {
|
|
4164
|
+
localStorage.setItem(storageKey, JSON.stringify(state));
|
|
4165
|
+
} catch {
|
|
4166
|
+
}
|
|
4167
|
+
};
|
|
4168
|
+
function TestBed({
|
|
4169
|
+
items,
|
|
4170
|
+
storageKey = "testbed:open-state",
|
|
4171
|
+
disablePersistence = false,
|
|
4172
|
+
title = "TestBed"
|
|
4173
|
+
}) {
|
|
4174
|
+
const [open, setOpen] = react.useState(false);
|
|
4175
|
+
const itemsRef = react.useRef(items);
|
|
4176
|
+
itemsRef.current = items;
|
|
4177
|
+
react.useEffect(() => {
|
|
4178
|
+
if (!isEnvBrowser() || disablePersistence) return;
|
|
4179
|
+
const persisted = loadPersistedState(storageKey);
|
|
4180
|
+
itemsRef.current.forEach((item) => {
|
|
4181
|
+
const persistedValue = persisted[item.key];
|
|
4182
|
+
if (typeof persistedValue === "boolean" && persistedValue !== item.active) {
|
|
4183
|
+
item.onToggle(persistedValue);
|
|
4184
|
+
}
|
|
4185
|
+
});
|
|
4186
|
+
}, []);
|
|
4187
|
+
if (!isEnvBrowser()) return null;
|
|
4188
|
+
const toggle = (item) => {
|
|
4189
|
+
const next = !item.active;
|
|
4190
|
+
item.onToggle(next);
|
|
4191
|
+
if (!disablePersistence) {
|
|
4192
|
+
const persisted = loadPersistedState(storageKey);
|
|
4193
|
+
persisted[item.key] = next;
|
|
4194
|
+
savePersistedState(storageKey, persisted);
|
|
4195
|
+
}
|
|
4196
|
+
};
|
|
4197
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4198
|
+
"div",
|
|
4199
|
+
{
|
|
4200
|
+
style: {
|
|
4201
|
+
position: "fixed",
|
|
4202
|
+
top: "1vh",
|
|
4203
|
+
left: "1vh",
|
|
4204
|
+
zIndex: 2147483647,
|
|
4205
|
+
pointerEvents: "auto",
|
|
4206
|
+
fontSize: "1.4vh"
|
|
4207
|
+
},
|
|
4208
|
+
children: [
|
|
4209
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4210
|
+
core.Flex,
|
|
4211
|
+
{
|
|
4212
|
+
align: "center",
|
|
4213
|
+
gap: "xs",
|
|
4214
|
+
px: "sm",
|
|
4215
|
+
py: "xs",
|
|
4216
|
+
onClick: () => setOpen((v) => !v),
|
|
4217
|
+
style: {
|
|
4218
|
+
cursor: "pointer",
|
|
4219
|
+
background: "rgba(0,0,0,0.55)",
|
|
4220
|
+
backdropFilter: "blur(0.6vh)",
|
|
4221
|
+
WebkitBackdropFilter: "blur(0.6vh)",
|
|
4222
|
+
border: "0.1vh solid rgba(255,255,255,0.1)",
|
|
4223
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
4224
|
+
userSelect: "none",
|
|
4225
|
+
minWidth: "16vh"
|
|
4226
|
+
},
|
|
4227
|
+
children: [
|
|
4228
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FlaskConical, { size: 14, color: "rgba(255,255,255,0.7)" }),
|
|
4229
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4230
|
+
core.Text,
|
|
4231
|
+
{
|
|
4232
|
+
size: "xs",
|
|
4233
|
+
ff: "Akrobat Bold",
|
|
4234
|
+
tt: "uppercase",
|
|
4235
|
+
lts: "0.08em",
|
|
4236
|
+
c: "rgba(255,255,255,0.85)",
|
|
4237
|
+
style: { flex: 1 },
|
|
4238
|
+
children: title
|
|
4239
|
+
}
|
|
4240
|
+
),
|
|
4241
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.ActionIcon, { size: "xs", variant: "transparent", c: "rgba(255,255,255,0.6)", children: open ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { size: 14 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 14 }) })
|
|
4242
|
+
]
|
|
4243
|
+
}
|
|
4244
|
+
),
|
|
4245
|
+
open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4246
|
+
core.Stack,
|
|
4247
|
+
{
|
|
4248
|
+
gap: 4,
|
|
4249
|
+
mt: "xxs",
|
|
4250
|
+
p: "xs",
|
|
4251
|
+
style: {
|
|
4252
|
+
background: "rgba(0,0,0,0.55)",
|
|
4253
|
+
backdropFilter: "blur(0.6vh)",
|
|
4254
|
+
WebkitBackdropFilter: "blur(0.6vh)",
|
|
4255
|
+
border: "0.1vh solid rgba(255,255,255,0.1)",
|
|
4256
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
4257
|
+
minWidth: "16vh",
|
|
4258
|
+
maxHeight: "80vh",
|
|
4259
|
+
overflowY: "auto"
|
|
4260
|
+
},
|
|
4261
|
+
children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4262
|
+
core.Flex,
|
|
4263
|
+
{
|
|
4264
|
+
align: "center",
|
|
4265
|
+
justify: "space-between",
|
|
4266
|
+
gap: "xs",
|
|
4267
|
+
px: "xs",
|
|
4268
|
+
py: "xxs",
|
|
4269
|
+
onClick: () => toggle(item),
|
|
4270
|
+
style: {
|
|
4271
|
+
cursor: "pointer",
|
|
4272
|
+
borderRadius: "var(--mantine-radius-xs)",
|
|
4273
|
+
background: item.active ? "rgba(245,158,11,0.15)" : "rgba(255,255,255,0.03)",
|
|
4274
|
+
border: `0.1vh solid ${item.active ? "rgba(245,158,11,0.35)" : "rgba(255,255,255,0.05)"}`,
|
|
4275
|
+
userSelect: "none"
|
|
4276
|
+
},
|
|
4277
|
+
children: [
|
|
4278
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4279
|
+
core.Text,
|
|
4280
|
+
{
|
|
4281
|
+
size: "xs",
|
|
4282
|
+
ff: "Akrobat Bold",
|
|
4283
|
+
c: item.active ? "#f59e0b" : "rgba(255,255,255,0.75)",
|
|
4284
|
+
children: item.label
|
|
4285
|
+
}
|
|
4286
|
+
),
|
|
4287
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4288
|
+
core.Text,
|
|
4289
|
+
{
|
|
4290
|
+
size: "xxs",
|
|
4291
|
+
ff: "Akrobat Bold",
|
|
4292
|
+
tt: "uppercase",
|
|
4293
|
+
lts: "0.06em",
|
|
4294
|
+
c: item.active ? "#f59e0b" : "rgba(255,255,255,0.35)",
|
|
4295
|
+
children: item.active ? "On" : "Off"
|
|
4296
|
+
}
|
|
4297
|
+
)
|
|
4298
|
+
]
|
|
4299
|
+
},
|
|
4300
|
+
item.key
|
|
4301
|
+
))
|
|
4302
|
+
}
|
|
4303
|
+
)
|
|
4304
|
+
]
|
|
4305
|
+
}
|
|
4306
|
+
);
|
|
4307
|
+
}
|
|
4085
4308
|
|
|
4086
4309
|
exports.AdminPageTitle = AdminPageTitle;
|
|
4087
4310
|
exports.AsyncSaveButton = AsyncSaveButton;
|
|
4088
4311
|
exports.BlipColorSelect = BlipColorSelect;
|
|
4089
4312
|
exports.BlipIconSelect = BlipIconSelect;
|
|
4090
4313
|
exports.BorderedIcon = BorderedIcon;
|
|
4314
|
+
exports.ConfigPanel = ConfigPanel;
|
|
4091
4315
|
exports.ConfirmModal = ConfirmModal;
|
|
4092
4316
|
exports.Counter = Counter;
|
|
4093
4317
|
exports.FiveMKeyBindInput = FiveMKeyBindInput;
|
|
@@ -4110,7 +4334,7 @@ exports.PromptModal = PromptModal;
|
|
|
4110
4334
|
exports.SegmentedControl = SegmentedControl;
|
|
4111
4335
|
exports.SegmentedProgress = SegmentedProgress;
|
|
4112
4336
|
exports.SelectItem = SelectItem;
|
|
4113
|
-
exports.
|
|
4337
|
+
exports.TestBed = TestBed;
|
|
4114
4338
|
exports.Title = Title;
|
|
4115
4339
|
exports.useModal = useModal;
|
|
4116
4340
|
exports.useModalActions = useModalActions;
|