dirk-cfx-react 1.1.58 → 1.1.62
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 +242 -46
- 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 +243 -48
- package/dist/components/index.js.map +1 -1
- package/dist/hooks/index.cjs +35 -24
- 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 +34 -23
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.cjs +277 -72
- 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 +276 -72
- package/dist/index.js.map +1 -1
- package/dist/providers/index.cjs.map +1 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/utils/index.cjs +4 -4
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +4 -4
- package/dist/utils/index.js.map +1 -1
- package/package.json +6 -7
package/dist/index.cjs
CHANGED
|
@@ -1335,10 +1335,8 @@ async function runFetches() {
|
|
|
1335
1335
|
var useAutoFetcher = () => {
|
|
1336
1336
|
React5.useEffect(() => {
|
|
1337
1337
|
if (isEnvBrowser()) return;
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
};
|
|
1341
|
-
run();
|
|
1338
|
+
runFetches().catch(() => {
|
|
1339
|
+
});
|
|
1342
1340
|
}, []);
|
|
1343
1341
|
};
|
|
1344
1342
|
var fetchLuaTable = (tableName, mockData) => {
|
|
@@ -1383,6 +1381,7 @@ var localeStore = zustand.create((set, get) => {
|
|
|
1383
1381
|
var locale = localeStore.getState().locale;
|
|
1384
1382
|
registerInitialFetch("GET_LOCALES", void 0).then((data) => {
|
|
1385
1383
|
localeStore.setState({ locales: data });
|
|
1384
|
+
}).catch(() => {
|
|
1386
1385
|
});
|
|
1387
1386
|
|
|
1388
1387
|
// src/utils/map.ts
|
|
@@ -1900,6 +1899,7 @@ registerInitialFetch("FETCH_ALL_ITEMS", null, {
|
|
|
1900
1899
|
}).then((fetchedItems) => {
|
|
1901
1900
|
if (!fetchedItems) return;
|
|
1902
1901
|
useItems.setState(fetchedItems);
|
|
1902
|
+
}).catch(() => {
|
|
1903
1903
|
});
|
|
1904
1904
|
|
|
1905
1905
|
// src/utils/inputMapper.ts
|
|
@@ -3282,7 +3282,7 @@ function Modal({
|
|
|
3282
3282
|
children: description2
|
|
3283
3283
|
}
|
|
3284
3284
|
) }),
|
|
3285
|
-
children
|
|
3285
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, minHeight: 0, display: "flex", flexDirection: "column" }, children })
|
|
3286
3286
|
]
|
|
3287
3287
|
}
|
|
3288
3288
|
)
|
|
@@ -3964,42 +3964,42 @@ var useNuiEvent = (action, handler) => {
|
|
|
3964
3964
|
}, [action]);
|
|
3965
3965
|
};
|
|
3966
3966
|
var _instance = null;
|
|
3967
|
-
function
|
|
3968
|
-
if (!_instance) throw new Error("[dirk-cfx-react]
|
|
3967
|
+
function getScriptConfigInstance() {
|
|
3968
|
+
if (!_instance) throw new Error("[dirk-cfx-react] createScriptConfig must be called before using ConfigPanel");
|
|
3969
3969
|
return _instance;
|
|
3970
3970
|
}
|
|
3971
|
-
function
|
|
3971
|
+
function createScriptConfig(defaultValue) {
|
|
3972
3972
|
const store = zustand.create(() => defaultValue);
|
|
3973
3973
|
let clientVersion = 0;
|
|
3974
|
-
const
|
|
3975
|
-
useNuiEvent("
|
|
3974
|
+
const useScriptConfigHooks = () => {
|
|
3975
|
+
useNuiEvent("UPDATE_SCRIPT_CONFIG", (data) => {
|
|
3976
3976
|
if (!data) return;
|
|
3977
3977
|
if (typeof data.clientVersion === "number") {
|
|
3978
3978
|
clientVersion = data.clientVersion;
|
|
3979
3979
|
}
|
|
3980
|
-
if (data.
|
|
3981
|
-
store.setState((prev) => ({ ...prev, ...data.
|
|
3980
|
+
if (data.config && typeof data.config === "object") {
|
|
3981
|
+
store.setState((prev) => ({ ...prev, ...data.config }));
|
|
3982
3982
|
}
|
|
3983
3983
|
});
|
|
3984
3984
|
};
|
|
3985
|
-
const
|
|
3985
|
+
const fetchScriptConfig = async () => {
|
|
3986
3986
|
try {
|
|
3987
|
-
const response = await fetchNui("
|
|
3988
|
-
if (response?.success && response.data?.
|
|
3989
|
-
store.setState(() => response.data.
|
|
3987
|
+
const response = await fetchNui("GET_FULL_SCRIPT_CONFIG");
|
|
3988
|
+
if (response?.success && response.data?.config) {
|
|
3989
|
+
store.setState(() => response.data.config);
|
|
3990
3990
|
if (typeof response.data.clientVersion === "number") {
|
|
3991
3991
|
clientVersion = response.data.clientVersion;
|
|
3992
3992
|
}
|
|
3993
|
-
return response.data.
|
|
3993
|
+
return response.data.config;
|
|
3994
3994
|
}
|
|
3995
3995
|
} catch {
|
|
3996
3996
|
}
|
|
3997
3997
|
return null;
|
|
3998
3998
|
};
|
|
3999
|
-
const
|
|
4000
|
-
store.setState((prev) => ({ ...prev, ...
|
|
4001
|
-
const response = await fetchNui("
|
|
4002
|
-
data:
|
|
3999
|
+
const updateScriptConfig = async (newConfig) => {
|
|
4000
|
+
store.setState((prev) => ({ ...prev, ...newConfig }));
|
|
4001
|
+
const response = await fetchNui("UPDATE_SCRIPT_CONFIG", {
|
|
4002
|
+
data: newConfig,
|
|
4003
4003
|
expectedVersion: clientVersion
|
|
4004
4004
|
});
|
|
4005
4005
|
if (response?.meta?.client_version != null) {
|
|
@@ -4010,18 +4010,29 @@ function createScriptSettings(defaultValue) {
|
|
|
4010
4010
|
}
|
|
4011
4011
|
return response;
|
|
4012
4012
|
};
|
|
4013
|
-
const
|
|
4014
|
-
return fetchNui("
|
|
4013
|
+
const getScriptConfigHistory = async (params = {}) => {
|
|
4014
|
+
return fetchNui("GET_SCRIPT_CONFIG_HISTORY", params);
|
|
4015
|
+
};
|
|
4016
|
+
const resetConfig = async () => {
|
|
4017
|
+
const response = await fetchNui("RESET_SCRIPT_CONFIG");
|
|
4018
|
+
if (response?.success) {
|
|
4019
|
+
const fresh = await fetchScriptConfig();
|
|
4020
|
+
if (fresh) {
|
|
4021
|
+
store.setState(() => fresh);
|
|
4022
|
+
}
|
|
4023
|
+
}
|
|
4024
|
+
return response;
|
|
4015
4025
|
};
|
|
4016
4026
|
_instance = {
|
|
4017
4027
|
store,
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4028
|
+
updateConfig: updateScriptConfig,
|
|
4029
|
+
resetConfig,
|
|
4030
|
+
getHistory: getScriptConfigHistory,
|
|
4031
|
+
fetchConfig: fetchScriptConfig
|
|
4021
4032
|
};
|
|
4022
|
-
return { store,
|
|
4033
|
+
return { store, updateScriptConfig, resetConfig, getScriptConfigHistory, useScriptConfigHooks, fetchScriptConfig };
|
|
4023
4034
|
}
|
|
4024
|
-
var
|
|
4035
|
+
var configPanelQueryClient = new reactQuery.QueryClient({
|
|
4025
4036
|
defaultOptions: { queries: { staleTime: 3e4, gcTime: 5 * 6e4 } }
|
|
4026
4037
|
});
|
|
4027
4038
|
function NavItemButton({
|
|
@@ -4065,7 +4076,7 @@ function NavItemButton({
|
|
|
4065
4076
|
}
|
|
4066
4077
|
);
|
|
4067
4078
|
}
|
|
4068
|
-
function
|
|
4079
|
+
function ConfigJsonModal({
|
|
4069
4080
|
onClose,
|
|
4070
4081
|
schema
|
|
4071
4082
|
}) {
|
|
@@ -4102,7 +4113,7 @@ function SettingsJsonModal({
|
|
|
4102
4113
|
setError(e.message);
|
|
4103
4114
|
}
|
|
4104
4115
|
};
|
|
4105
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "
|
|
4116
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "Config JSON", icon: lucideReact.Code2, iconColor: color, onClose, width: "60vh", maxHeight: "80vh", zIndex: 200, children: [
|
|
4106
4117
|
/* @__PURE__ */ jsxRuntime.jsxs(core.Box, { flex: 1, p: "0.8vh", style: { overflowY: "auto" }, children: [
|
|
4107
4118
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4108
4119
|
core.JsonInput,
|
|
@@ -4244,10 +4255,10 @@ function HistoryTableHeader() {
|
|
|
4244
4255
|
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: "Version" })
|
|
4245
4256
|
] });
|
|
4246
4257
|
}
|
|
4247
|
-
function
|
|
4258
|
+
function ConfigHistoryModal({
|
|
4248
4259
|
onClose
|
|
4249
4260
|
}) {
|
|
4250
|
-
const { getHistory } =
|
|
4261
|
+
const { getHistory } = getScriptConfigInstance();
|
|
4251
4262
|
const theme2 = core.useMantineTheme();
|
|
4252
4263
|
const color = theme2.colors[theme2.primaryColor][5];
|
|
4253
4264
|
const [queryInput, setQueryInput] = React5.useState("");
|
|
@@ -4259,7 +4270,7 @@ function SettingsHistoryModal({
|
|
|
4259
4270
|
const [expandedKey, setExpandedKey] = React5.useState(null);
|
|
4260
4271
|
const filters = React5.useMemo(() => ({ query, path, admin }), [query, path, admin]);
|
|
4261
4272
|
const historyQuery = reactQuery.useInfiniteQuery({
|
|
4262
|
-
queryKey: ["
|
|
4273
|
+
queryKey: ["scriptConfigHistory", filters],
|
|
4263
4274
|
initialPageParam: 0,
|
|
4264
4275
|
queryFn: async ({ pageParam }) => {
|
|
4265
4276
|
const response = await getHistory({
|
|
@@ -4270,7 +4281,7 @@ function SettingsHistoryModal({
|
|
|
4270
4281
|
admin: filters.admin || void 0
|
|
4271
4282
|
});
|
|
4272
4283
|
if (!response?.success || !response.data) {
|
|
4273
|
-
throw new Error(response?._error || "Failed to load
|
|
4284
|
+
throw new Error(response?._error || "Failed to load config history");
|
|
4274
4285
|
}
|
|
4275
4286
|
return response.data;
|
|
4276
4287
|
},
|
|
@@ -4284,7 +4295,7 @@ function SettingsHistoryModal({
|
|
|
4284
4295
|
historyQuery.fetchNextPage();
|
|
4285
4296
|
}
|
|
4286
4297
|
};
|
|
4287
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "
|
|
4298
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "Config History", icon: lucideReact.History, iconColor: color, onClose, width: "88vh", maxHeight: "82vh", zIndex: 260, children: [
|
|
4288
4299
|
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { flex: 1, minHeight: 0 }, children: [
|
|
4289
4300
|
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { gap: "xs", p: "sm", style: { borderBottom: `0.1vh solid ${core.alpha(theme2.colors.dark[7], 0.8)}` }, children: [
|
|
4290
4301
|
/* @__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 } }),
|
|
@@ -4333,7 +4344,7 @@ function SettingsHistoryModal({
|
|
|
4333
4344
|
) })
|
|
4334
4345
|
] });
|
|
4335
4346
|
}
|
|
4336
|
-
function
|
|
4347
|
+
function ConfigPanelInner({
|
|
4337
4348
|
navItems,
|
|
4338
4349
|
title,
|
|
4339
4350
|
subtitle,
|
|
@@ -4342,28 +4353,37 @@ function SettingsPanelInner({
|
|
|
4342
4353
|
onClose,
|
|
4343
4354
|
schema,
|
|
4344
4355
|
resetConfirmText,
|
|
4345
|
-
|
|
4356
|
+
defaultConfig,
|
|
4346
4357
|
width,
|
|
4347
4358
|
height
|
|
4348
4359
|
}) {
|
|
4349
|
-
const {
|
|
4360
|
+
const { updateConfig, resetConfig, getHistory } = getScriptConfigInstance();
|
|
4350
4361
|
const form = useForm();
|
|
4351
4362
|
const theme2 = core.useMantineTheme();
|
|
4352
4363
|
const color = theme2.colors[theme2.primaryColor][5];
|
|
4353
4364
|
const version = useSettings((s) => s.resourceVersion);
|
|
4354
4365
|
const [activeTab, setActiveTab] = React5.useState(navItems[0]?.id ?? "");
|
|
4366
|
+
const firstMountRef = React5.useRef(true);
|
|
4355
4367
|
const [jsonOpen, setJsonOpen] = React5.useState(false);
|
|
4356
4368
|
const [historyOpen, setHistoryOpen] = React5.useState(false);
|
|
4357
4369
|
const [resetOpen, setResetOpen] = React5.useState(false);
|
|
4358
|
-
const [
|
|
4370
|
+
const [pendingAction, setPendingAction] = React5.useState(null);
|
|
4359
4371
|
const changedCount = form.changedCount ?? 0;
|
|
4360
4372
|
const isDirty = changedCount > 0;
|
|
4373
|
+
const goBack = () => fetchNui("CONFIG_PANEL_BACK");
|
|
4374
|
+
const handleBack = () => {
|
|
4375
|
+
if (isDirty) {
|
|
4376
|
+
setPendingAction("back");
|
|
4377
|
+
return;
|
|
4378
|
+
}
|
|
4379
|
+
goBack();
|
|
4380
|
+
};
|
|
4361
4381
|
React5.useEffect(() => {
|
|
4362
4382
|
function handleKeyDown(e) {
|
|
4363
4383
|
if (e.key !== "Escape") return;
|
|
4364
4384
|
if (isDirty) {
|
|
4365
4385
|
e.preventDefault();
|
|
4366
|
-
|
|
4386
|
+
setPendingAction("close");
|
|
4367
4387
|
return;
|
|
4368
4388
|
}
|
|
4369
4389
|
onClose();
|
|
@@ -4372,34 +4392,40 @@ function SettingsPanelInner({
|
|
|
4372
4392
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4373
4393
|
}, [isDirty, onClose]);
|
|
4374
4394
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4375
|
-
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4376
|
-
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4395
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsxRuntime.jsx(ConfigJsonModal, { onClose: () => setJsonOpen(false), schema }) }),
|
|
4396
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsxRuntime.jsx(ConfigHistoryModal, { onClose: () => setHistoryOpen(false) }) }),
|
|
4377
4397
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: resetOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4378
4398
|
ConfirmModal,
|
|
4379
4399
|
{
|
|
4380
4400
|
title: "Reset to Defaults",
|
|
4381
|
-
description: "This will permanently reset ALL
|
|
4382
|
-
confirmLabel: "Reset
|
|
4401
|
+
description: "This will permanently reset ALL config back to the defaults. Every value you have configured will be overwritten. This cannot be undone.",
|
|
4402
|
+
confirmLabel: "Reset Config",
|
|
4383
4403
|
confirmText: resetConfirmText,
|
|
4384
|
-
onConfirm: () => {
|
|
4385
|
-
updateSettings(defaultSettings).then(() => form.reinitialize(cloneSettings(defaultSettings)));
|
|
4404
|
+
onConfirm: async () => {
|
|
4386
4405
|
setResetOpen(false);
|
|
4406
|
+
const result = await resetConfig();
|
|
4407
|
+
if (result?.success) {
|
|
4408
|
+
const { store } = getScriptConfigInstance();
|
|
4409
|
+
form.reinitialize(cloneConfig(store.getState()));
|
|
4410
|
+
}
|
|
4387
4411
|
},
|
|
4388
4412
|
onClose: () => setResetOpen(false),
|
|
4389
4413
|
zIndex: 300
|
|
4390
4414
|
}
|
|
4391
4415
|
) }),
|
|
4392
|
-
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children:
|
|
4416
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: pendingAction !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4393
4417
|
ConfirmModal,
|
|
4394
4418
|
{
|
|
4395
4419
|
title: "Discard Unsaved Changes?",
|
|
4396
|
-
description: "You have unsaved changes. Closing now will discard them.",
|
|
4397
|
-
confirmLabel: "Close Without Saving",
|
|
4420
|
+
description: pendingAction === "back" ? "You have unsaved changes. Going back now will discard them." : "You have unsaved changes. Closing now will discard them.",
|
|
4421
|
+
confirmLabel: pendingAction === "back" ? "Go Back Without Saving" : "Close Without Saving",
|
|
4398
4422
|
onConfirm: () => {
|
|
4399
|
-
|
|
4400
|
-
|
|
4423
|
+
const action = pendingAction;
|
|
4424
|
+
setPendingAction(null);
|
|
4425
|
+
if (action === "back") goBack();
|
|
4426
|
+
else onClose();
|
|
4401
4427
|
},
|
|
4402
|
-
onClose: () =>
|
|
4428
|
+
onClose: () => setPendingAction(null),
|
|
4403
4429
|
zIndex: 300
|
|
4404
4430
|
}
|
|
4405
4431
|
) }),
|
|
@@ -4426,9 +4452,33 @@ function SettingsPanelInner({
|
|
|
4426
4452
|
exit: { scale: 0.3, opacity: 0, transform: "translate(-50%, -50%)" },
|
|
4427
4453
|
children: [
|
|
4428
4454
|
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { width: "18vh", flexShrink: 0, borderRight: `0.1vh solid ${core.alpha(theme2.colors.dark[6], 0.8)}`, background: core.alpha(theme2.colors.dark[8], 0.6), overflow: "hidden" }, children: [
|
|
4429
|
-
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "
|
|
4430
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4431
|
-
|
|
4455
|
+
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "0.6vh", px: "sm", py: "sm", style: { borderBottom: `0.1vh solid ${core.alpha(theme2.colors.dark[6], 0.5)}`, flexShrink: 0 }, children: [
|
|
4456
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4457
|
+
framerMotion.motion.button,
|
|
4458
|
+
{
|
|
4459
|
+
title: "Back to script list",
|
|
4460
|
+
onClick: handleBack,
|
|
4461
|
+
whileHover: { background: core.alpha(color, 0.16), borderColor: core.alpha(color, 0.45) },
|
|
4462
|
+
whileTap: { scale: 0.95 },
|
|
4463
|
+
style: {
|
|
4464
|
+
aspectRatio: "1 / 1",
|
|
4465
|
+
height: "2.4vh",
|
|
4466
|
+
background: core.alpha(color, 0.08),
|
|
4467
|
+
border: `0.1vh solid ${core.alpha(color, 0.3)}`,
|
|
4468
|
+
borderRadius: theme2.radius.xs,
|
|
4469
|
+
cursor: "pointer",
|
|
4470
|
+
display: "flex",
|
|
4471
|
+
alignItems: "center",
|
|
4472
|
+
justifyContent: "center",
|
|
4473
|
+
flexShrink: 0
|
|
4474
|
+
},
|
|
4475
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { size: "1.4vh", color })
|
|
4476
|
+
}
|
|
4477
|
+
),
|
|
4478
|
+
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { minWidth: 0, lineHeight: 1 }, children: [
|
|
4479
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { size: "lg", ff: "Akrobat Bold", tt: "uppercase", lts: "0.04em", truncate: true, children: title }),
|
|
4480
|
+
subtitle && /* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.08em", c: color, truncate: true, children: subtitle })
|
|
4481
|
+
] })
|
|
4432
4482
|
] }),
|
|
4433
4483
|
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { gap: "xxs", px: "xs", py: "xs", style: { borderBottom: `0.1vh solid ${core.alpha(theme2.colors.dark[6], 0.4)}`, flexShrink: 0 }, children: [
|
|
4434
4484
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -4531,7 +4581,7 @@ function SettingsPanelInner({
|
|
|
4531
4581
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4532
4582
|
framerMotion.motion.div,
|
|
4533
4583
|
{
|
|
4534
|
-
initial: { opacity: 0, y: 4 },
|
|
4584
|
+
initial: firstMountRef.current ? (firstMountRef.current = false, false) : { opacity: 0, y: 4 },
|
|
4535
4585
|
animate: { opacity: 1, y: 0 },
|
|
4536
4586
|
exit: { opacity: 0, y: -4 },
|
|
4537
4587
|
transition: { duration: 0.15 },
|
|
@@ -4545,15 +4595,15 @@ function SettingsPanelInner({
|
|
|
4545
4595
|
)
|
|
4546
4596
|
] });
|
|
4547
4597
|
}
|
|
4548
|
-
function
|
|
4598
|
+
function cloneConfig(value) {
|
|
4549
4599
|
return JSON.parse(JSON.stringify(value));
|
|
4550
4600
|
}
|
|
4551
4601
|
function ServerOnlyFetcher() {
|
|
4552
|
-
const {
|
|
4602
|
+
const { fetchConfig } = getScriptConfigInstance();
|
|
4553
4603
|
const { reinitialize } = useFormActions();
|
|
4554
4604
|
React5.useEffect(() => {
|
|
4555
4605
|
let cancelled = false;
|
|
4556
|
-
|
|
4606
|
+
fetchConfig().then((full) => {
|
|
4557
4607
|
if (!cancelled && full) reinitialize(full);
|
|
4558
4608
|
}).catch(() => {
|
|
4559
4609
|
});
|
|
@@ -4564,28 +4614,28 @@ function ServerOnlyFetcher() {
|
|
|
4564
4614
|
return null;
|
|
4565
4615
|
}
|
|
4566
4616
|
var defaultOnClose = () => fetchNui("CLOSE_ADMIN_SECTION");
|
|
4567
|
-
function
|
|
4617
|
+
function ConfigPanel(props) {
|
|
4568
4618
|
const { open, onClose = defaultOnClose } = props;
|
|
4569
|
-
const { store,
|
|
4619
|
+
const { store, updateConfig } = getScriptConfigInstance();
|
|
4570
4620
|
const [isSaving, setIsSaving] = React5.useState(false);
|
|
4571
4621
|
if (!open) return null;
|
|
4572
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client:
|
|
4622
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: configPanelQueryClient, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4573
4623
|
FormProvider,
|
|
4574
4624
|
{
|
|
4575
|
-
initialValues:
|
|
4625
|
+
initialValues: cloneConfig(store.getState()),
|
|
4576
4626
|
onSubmit: async (form) => {
|
|
4577
4627
|
if (isSaving) return;
|
|
4578
4628
|
setIsSaving(true);
|
|
4579
4629
|
try {
|
|
4580
|
-
const result = await
|
|
4630
|
+
const result = await updateConfig(form.values);
|
|
4581
4631
|
if (result?.success) {
|
|
4582
|
-
form.reinitialize(
|
|
4583
|
-
|
|
4632
|
+
form.reinitialize(cloneConfig(form.values));
|
|
4633
|
+
configPanelQueryClient.invalidateQueries({ queryKey: ["scriptConfigHistory"] });
|
|
4584
4634
|
return;
|
|
4585
4635
|
}
|
|
4586
|
-
form.reinitialize(
|
|
4636
|
+
form.reinitialize(cloneConfig(store.getState()));
|
|
4587
4637
|
if (result?._error) {
|
|
4588
|
-
console.warn(`[
|
|
4638
|
+
console.warn(`[ConfigPanel] config save failed: ${result._error}`);
|
|
4589
4639
|
}
|
|
4590
4640
|
} finally {
|
|
4591
4641
|
setIsSaving(false);
|
|
@@ -4594,7 +4644,7 @@ function SettingsPanel(props) {
|
|
|
4594
4644
|
children: [
|
|
4595
4645
|
/* @__PURE__ */ jsxRuntime.jsx(ServerOnlyFetcher, {}),
|
|
4596
4646
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4597
|
-
|
|
4647
|
+
ConfigPanelInner,
|
|
4598
4648
|
{
|
|
4599
4649
|
...props,
|
|
4600
4650
|
onClose,
|
|
@@ -4802,6 +4852,160 @@ function AdminPageTitle(props) {
|
|
|
4802
4852
|
/* @__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) })
|
|
4803
4853
|
] });
|
|
4804
4854
|
}
|
|
4855
|
+
var loadPersistedState = (storageKey) => {
|
|
4856
|
+
try {
|
|
4857
|
+
const raw = localStorage.getItem(storageKey);
|
|
4858
|
+
return raw ? JSON.parse(raw) : {};
|
|
4859
|
+
} catch {
|
|
4860
|
+
return {};
|
|
4861
|
+
}
|
|
4862
|
+
};
|
|
4863
|
+
var savePersistedState = (storageKey, state) => {
|
|
4864
|
+
try {
|
|
4865
|
+
localStorage.setItem(storageKey, JSON.stringify(state));
|
|
4866
|
+
} catch {
|
|
4867
|
+
}
|
|
4868
|
+
};
|
|
4869
|
+
function TestBed({
|
|
4870
|
+
items,
|
|
4871
|
+
storageKey = "testbed:open-state",
|
|
4872
|
+
disablePersistence = false,
|
|
4873
|
+
title = "TestBed"
|
|
4874
|
+
}) {
|
|
4875
|
+
const [open, setOpen] = React5.useState(false);
|
|
4876
|
+
const itemsRef = React5.useRef(items);
|
|
4877
|
+
itemsRef.current = items;
|
|
4878
|
+
React5.useEffect(() => {
|
|
4879
|
+
if (!isEnvBrowser() || disablePersistence) return;
|
|
4880
|
+
const persisted = loadPersistedState(storageKey);
|
|
4881
|
+
itemsRef.current.forEach((item) => {
|
|
4882
|
+
const persistedValue = persisted[item.key];
|
|
4883
|
+
if (typeof persistedValue === "boolean" && persistedValue !== item.active) {
|
|
4884
|
+
item.onToggle(persistedValue);
|
|
4885
|
+
}
|
|
4886
|
+
});
|
|
4887
|
+
}, []);
|
|
4888
|
+
if (!isEnvBrowser()) return null;
|
|
4889
|
+
const toggle = (item) => {
|
|
4890
|
+
const next = !item.active;
|
|
4891
|
+
item.onToggle(next);
|
|
4892
|
+
if (!disablePersistence) {
|
|
4893
|
+
const persisted = loadPersistedState(storageKey);
|
|
4894
|
+
persisted[item.key] = next;
|
|
4895
|
+
savePersistedState(storageKey, persisted);
|
|
4896
|
+
}
|
|
4897
|
+
};
|
|
4898
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4899
|
+
"div",
|
|
4900
|
+
{
|
|
4901
|
+
style: {
|
|
4902
|
+
position: "fixed",
|
|
4903
|
+
top: "1vh",
|
|
4904
|
+
left: "1vh",
|
|
4905
|
+
zIndex: 2147483647,
|
|
4906
|
+
pointerEvents: "auto",
|
|
4907
|
+
fontSize: "1.4vh"
|
|
4908
|
+
},
|
|
4909
|
+
children: [
|
|
4910
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4911
|
+
core.Flex,
|
|
4912
|
+
{
|
|
4913
|
+
align: "center",
|
|
4914
|
+
gap: "xs",
|
|
4915
|
+
px: "sm",
|
|
4916
|
+
py: "xs",
|
|
4917
|
+
onClick: () => setOpen((v) => !v),
|
|
4918
|
+
style: {
|
|
4919
|
+
cursor: "pointer",
|
|
4920
|
+
background: "rgba(0,0,0,0.55)",
|
|
4921
|
+
backdropFilter: "blur(0.6vh)",
|
|
4922
|
+
WebkitBackdropFilter: "blur(0.6vh)",
|
|
4923
|
+
border: "0.1vh solid rgba(255,255,255,0.1)",
|
|
4924
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
4925
|
+
userSelect: "none",
|
|
4926
|
+
minWidth: "16vh"
|
|
4927
|
+
},
|
|
4928
|
+
children: [
|
|
4929
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FlaskConical, { size: 14, color: "rgba(255,255,255,0.7)" }),
|
|
4930
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4931
|
+
core.Text,
|
|
4932
|
+
{
|
|
4933
|
+
size: "xs",
|
|
4934
|
+
ff: "Akrobat Bold",
|
|
4935
|
+
tt: "uppercase",
|
|
4936
|
+
lts: "0.08em",
|
|
4937
|
+
c: "rgba(255,255,255,0.85)",
|
|
4938
|
+
style: { flex: 1 },
|
|
4939
|
+
children: title
|
|
4940
|
+
}
|
|
4941
|
+
),
|
|
4942
|
+
/* @__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 }) })
|
|
4943
|
+
]
|
|
4944
|
+
}
|
|
4945
|
+
),
|
|
4946
|
+
open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4947
|
+
core.Stack,
|
|
4948
|
+
{
|
|
4949
|
+
gap: 4,
|
|
4950
|
+
mt: "xxs",
|
|
4951
|
+
p: "xs",
|
|
4952
|
+
style: {
|
|
4953
|
+
background: "rgba(0,0,0,0.55)",
|
|
4954
|
+
backdropFilter: "blur(0.6vh)",
|
|
4955
|
+
WebkitBackdropFilter: "blur(0.6vh)",
|
|
4956
|
+
border: "0.1vh solid rgba(255,255,255,0.1)",
|
|
4957
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
4958
|
+
minWidth: "16vh",
|
|
4959
|
+
maxHeight: "80vh",
|
|
4960
|
+
overflowY: "auto"
|
|
4961
|
+
},
|
|
4962
|
+
children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4963
|
+
core.Flex,
|
|
4964
|
+
{
|
|
4965
|
+
align: "center",
|
|
4966
|
+
justify: "space-between",
|
|
4967
|
+
gap: "xs",
|
|
4968
|
+
px: "xs",
|
|
4969
|
+
py: "xxs",
|
|
4970
|
+
onClick: () => toggle(item),
|
|
4971
|
+
style: {
|
|
4972
|
+
cursor: "pointer",
|
|
4973
|
+
borderRadius: "var(--mantine-radius-xs)",
|
|
4974
|
+
background: item.active ? "rgba(245,158,11,0.15)" : "rgba(255,255,255,0.03)",
|
|
4975
|
+
border: `0.1vh solid ${item.active ? "rgba(245,158,11,0.35)" : "rgba(255,255,255,0.05)"}`,
|
|
4976
|
+
userSelect: "none"
|
|
4977
|
+
},
|
|
4978
|
+
children: [
|
|
4979
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4980
|
+
core.Text,
|
|
4981
|
+
{
|
|
4982
|
+
size: "xs",
|
|
4983
|
+
ff: "Akrobat Bold",
|
|
4984
|
+
c: item.active ? "#f59e0b" : "rgba(255,255,255,0.75)",
|
|
4985
|
+
children: item.label
|
|
4986
|
+
}
|
|
4987
|
+
),
|
|
4988
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4989
|
+
core.Text,
|
|
4990
|
+
{
|
|
4991
|
+
size: "xxs",
|
|
4992
|
+
ff: "Akrobat Bold",
|
|
4993
|
+
tt: "uppercase",
|
|
4994
|
+
lts: "0.06em",
|
|
4995
|
+
c: item.active ? "#f59e0b" : "rgba(255,255,255,0.35)",
|
|
4996
|
+
children: item.active ? "On" : "Off"
|
|
4997
|
+
}
|
|
4998
|
+
)
|
|
4999
|
+
]
|
|
5000
|
+
},
|
|
5001
|
+
item.key
|
|
5002
|
+
))
|
|
5003
|
+
}
|
|
5004
|
+
)
|
|
5005
|
+
]
|
|
5006
|
+
}
|
|
5007
|
+
);
|
|
5008
|
+
}
|
|
4805
5009
|
function useTornEdges() {
|
|
4806
5010
|
const game = useSettings((state) => state.game);
|
|
4807
5011
|
return game === "rdr3" ? "torn-edge-wrapper" : "";
|
|
@@ -5103,6 +5307,7 @@ exports.AsyncSaveButton = AsyncSaveButton;
|
|
|
5103
5307
|
exports.BlipColorSelect = BlipColorSelect;
|
|
5104
5308
|
exports.BlipIconSelect = BlipIconSelect;
|
|
5105
5309
|
exports.BorderedIcon = BorderedIcon;
|
|
5310
|
+
exports.ConfigPanel = ConfigPanel;
|
|
5106
5311
|
exports.ConfirmModal = ConfirmModal;
|
|
5107
5312
|
exports.Counter = Counter;
|
|
5108
5313
|
exports.DirkProvider = DirkProvider;
|
|
@@ -5129,13 +5334,13 @@ exports.PromptModal = PromptModal;
|
|
|
5129
5334
|
exports.SegmentedControl = SegmentedControl;
|
|
5130
5335
|
exports.SegmentedProgress = SegmentedProgress;
|
|
5131
5336
|
exports.SelectItem = SelectItem;
|
|
5132
|
-
exports.
|
|
5337
|
+
exports.TestBed = TestBed;
|
|
5133
5338
|
exports.Title = Title;
|
|
5134
5339
|
exports.TornEdgeSVGFilter = TornEdgeSVGFilter;
|
|
5135
5340
|
exports.colorWithAlpha = colorWithAlpha;
|
|
5136
5341
|
exports.copyToClipboard = copyToClipboard;
|
|
5137
5342
|
exports.createFormStore = createFormStore;
|
|
5138
|
-
exports.
|
|
5343
|
+
exports.createScriptConfig = createScriptConfig;
|
|
5139
5344
|
exports.createSkill = createSkill;
|
|
5140
5345
|
exports.extractDefaults = extractDefaults;
|
|
5141
5346
|
exports.fetchLuaTable = fetchLuaTable;
|
|
@@ -5143,7 +5348,7 @@ exports.fetchNui = fetchNui;
|
|
|
5143
5348
|
exports.gameToMap = gameToMap;
|
|
5144
5349
|
exports.getImageShape = getImageShape;
|
|
5145
5350
|
exports.getItemImageUrl = getItemImageUrl;
|
|
5146
|
-
exports.
|
|
5351
|
+
exports.getScriptConfigInstance = getScriptConfigInstance;
|
|
5147
5352
|
exports.initialFetches = initialFetches;
|
|
5148
5353
|
exports.internalEvent = internalEvent;
|
|
5149
5354
|
exports.isEnvBrowser = isEnvBrowser;
|