dirk-cfx-react 1.1.89 → 1.1.91
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 +499 -247
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.cts +39 -9
- package/dist/components/index.d.ts +39 -9
- package/dist/components/index.js +500 -249
- package/dist/components/index.js.map +1 -1
- package/dist/hooks/index.cjs +22 -12
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.js +22 -12
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.cjs +502 -248
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -2
- package/dist/index.d.ts +43 -2
- package/dist/index.js +500 -250
- package/dist/index.js.map +1 -1
- package/dist/providers/index.cjs +51 -17
- package/dist/providers/index.cjs.map +1 -1
- package/dist/providers/index.js +51 -17
- package/dist/providers/index.js.map +1 -1
- package/dist/utils/index.cjs +51 -17
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.js +51 -17
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ var core = require('@mantine/core');
|
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
var react = require('react');
|
|
6
6
|
var zustand = require('zustand');
|
|
7
|
+
var zod = require('zod');
|
|
7
8
|
var reactFontawesome = require('@fortawesome/react-fontawesome');
|
|
8
9
|
var framerMotion = require('framer-motion');
|
|
9
10
|
var lucideReact = require('lucide-react');
|
|
@@ -1289,6 +1290,32 @@ function colorWithAlpha(color, alpha17) {
|
|
|
1289
1290
|
|
|
1290
1291
|
// src/utils/misc.ts
|
|
1291
1292
|
var isEnvBrowser = () => !window.invokeNative;
|
|
1293
|
+
var DEFAULT_PALETTE = [
|
|
1294
|
+
"#f0f4ff",
|
|
1295
|
+
"#d9e3ff",
|
|
1296
|
+
"#bfcfff",
|
|
1297
|
+
"#a6bbff",
|
|
1298
|
+
"#8ca7ff",
|
|
1299
|
+
"#7393ff",
|
|
1300
|
+
"#5a7fff",
|
|
1301
|
+
"#406bff",
|
|
1302
|
+
"#2547ff",
|
|
1303
|
+
"#0b33ff"
|
|
1304
|
+
];
|
|
1305
|
+
zod.z.object({
|
|
1306
|
+
useOverride: zod.z.boolean(),
|
|
1307
|
+
primaryColor: zod.z.string(),
|
|
1308
|
+
primaryShade: zod.z.number(),
|
|
1309
|
+
customTheme: zod.z.array(zod.z.string())
|
|
1310
|
+
});
|
|
1311
|
+
var defaultThemeOverride = {
|
|
1312
|
+
useOverride: false,
|
|
1313
|
+
primaryColor: "dirk",
|
|
1314
|
+
primaryShade: 5,
|
|
1315
|
+
customTheme: DEFAULT_PALETTE
|
|
1316
|
+
};
|
|
1317
|
+
|
|
1318
|
+
// src/utils/useSettings.ts
|
|
1292
1319
|
var useSettings = zustand.create(() => ({
|
|
1293
1320
|
currency: "$",
|
|
1294
1321
|
game: "fivem",
|
|
@@ -1296,18 +1323,7 @@ var useSettings = zustand.create(() => ({
|
|
|
1296
1323
|
primaryShade: 9,
|
|
1297
1324
|
itemImgPath: "",
|
|
1298
1325
|
resourceVersion: "dev",
|
|
1299
|
-
customTheme:
|
|
1300
|
-
"#f0f4ff",
|
|
1301
|
-
"#d9e3ff",
|
|
1302
|
-
"#bfcfff",
|
|
1303
|
-
"#a6bbff",
|
|
1304
|
-
"#8ca7ff",
|
|
1305
|
-
"#7393ff",
|
|
1306
|
-
"#5a7fff",
|
|
1307
|
-
"#406bff",
|
|
1308
|
-
"#2547ff",
|
|
1309
|
-
"#0b33ff"
|
|
1310
|
-
]
|
|
1326
|
+
customTheme: DEFAULT_PALETTE
|
|
1311
1327
|
}));
|
|
1312
1328
|
|
|
1313
1329
|
// src/utils/fetchNui.ts
|
|
@@ -1350,11 +1366,35 @@ function reportMissingLocale(key) {
|
|
|
1350
1366
|
fetchNui("REPORT_MISSING_LOCALE", { key }).catch(() => {
|
|
1351
1367
|
});
|
|
1352
1368
|
}
|
|
1369
|
+
var PACKAGE_DEFAULTS = {
|
|
1370
|
+
"OccupantsDesc": "Here you can view and manage the occupants of your traphouse. These occupants can be used mainly for selling drugs to the NPCs surrounding your traphouse. However they have other uses to so be careful who you add as an occupant.",
|
|
1371
|
+
"cfgpanel_discard": "Discard",
|
|
1372
|
+
"cfgpanel_manual_edit": "Manual Edit",
|
|
1373
|
+
"cfgpanel_reset_defaults": "Reset Defaults",
|
|
1374
|
+
"cfgpanel_version": "Version",
|
|
1375
|
+
"cfgpanel_back_title": "Back to script list",
|
|
1376
|
+
"cfgpanel_undo": "Undo",
|
|
1377
|
+
"cfgpanel_redo": "Redo",
|
|
1378
|
+
"cfgpanel_save": "Save",
|
|
1379
|
+
"cfgpanel_saving": "Saving...",
|
|
1380
|
+
"cfgpanel_history": "History",
|
|
1381
|
+
"cfgpanel_reset_title": "Reset to Defaults",
|
|
1382
|
+
"cfgpanel_reset_desc": "This will permanently reset ALL config back to the defaults. Every value you have configured will be overwritten. This cannot be undone.",
|
|
1383
|
+
"cfgpanel_reset_confirm": "Reset Config",
|
|
1384
|
+
"cfgpanel_discard_title": "Discard Unsaved Changes?",
|
|
1385
|
+
"cfgpanel_discard_desc_back": "You have unsaved changes. Going back now will discard them.",
|
|
1386
|
+
"cfgpanel_discard_desc_close": "You have unsaved changes. Closing now will discard them.",
|
|
1387
|
+
"cfgpanel_discard_confirm_back": "Go Back Without Saving",
|
|
1388
|
+
"cfgpanel_discard_confirm_close": "Close Without Saving",
|
|
1389
|
+
"cfgpanel_json_title": "Config JSON",
|
|
1390
|
+
"cfgpanel_cancel": "Cancel",
|
|
1391
|
+
"cfgpanel_apply": "Apply",
|
|
1392
|
+
"cfgpanel_history_title": "Config History",
|
|
1393
|
+
"cfgpanel_close": "Close"
|
|
1394
|
+
};
|
|
1353
1395
|
var localeStore = zustand.create((set, get) => {
|
|
1354
1396
|
return {
|
|
1355
|
-
locales: {
|
|
1356
|
-
"OccupantsDesc": "Here you can view and manage the occupants of your traphouse. These occupants can be used mainly for selling drugs to the NPCs surrounding your traphouse. However they have other uses to so be careful who you add as an occupant."
|
|
1357
|
-
},
|
|
1397
|
+
locales: { ...PACKAGE_DEFAULTS },
|
|
1358
1398
|
locale: (key, ...args) => {
|
|
1359
1399
|
const exists = get().locales[key];
|
|
1360
1400
|
if (!exists) reportMissingLocale(key);
|
|
@@ -1368,7 +1408,7 @@ var localeStore = zustand.create((set, get) => {
|
|
|
1368
1408
|
});
|
|
1369
1409
|
var locale = localeStore.getState().locale;
|
|
1370
1410
|
registerInitialFetch("GET_LOCALES", void 0).then((data) => {
|
|
1371
|
-
localeStore.setState({ locales: data });
|
|
1411
|
+
localeStore.setState({ locales: { ...PACKAGE_DEFAULTS, ...data } });
|
|
1372
1412
|
}).catch(() => {
|
|
1373
1413
|
});
|
|
1374
1414
|
if (typeof window !== "undefined") {
|
|
@@ -1377,7 +1417,7 @@ if (typeof window !== "undefined") {
|
|
|
1377
1417
|
if (!msg || msg.action !== "UPDATE_DIRK_LIB_LOCALES") return;
|
|
1378
1418
|
if (!msg.data || typeof msg.data !== "object") return;
|
|
1379
1419
|
if (Object.keys(msg.data).length === 0) return;
|
|
1380
|
-
localeStore.setState({ locales: msg.data });
|
|
1420
|
+
localeStore.setState({ locales: { ...PACKAGE_DEFAULTS, ...msg.data } });
|
|
1381
1421
|
});
|
|
1382
1422
|
}
|
|
1383
1423
|
|
|
@@ -3137,11 +3177,11 @@ function ConfirmModal({
|
|
|
3137
3177
|
placeholder: confirmText,
|
|
3138
3178
|
value: typed,
|
|
3139
3179
|
onChange: (e) => setTyped(e.currentTarget.value),
|
|
3140
|
-
styles: (
|
|
3180
|
+
styles: (t4) => ({
|
|
3141
3181
|
input: {
|
|
3142
|
-
backgroundColor: core.alpha(
|
|
3182
|
+
backgroundColor: core.alpha(t4.colors.dark[7], 0.5),
|
|
3143
3183
|
border: `0.1vh solid ${core.alpha(
|
|
3144
|
-
typed === confirmText ? "#ef4444" :
|
|
3184
|
+
typed === confirmText ? "#ef4444" : t4.colors.dark[5],
|
|
3145
3185
|
0.5
|
|
3146
3186
|
)}`,
|
|
3147
3187
|
color: "rgba(255,255,255,0.85)",
|
|
@@ -3786,7 +3826,7 @@ function useAdminState(key, initial) {
|
|
|
3786
3826
|
react.useEffect(() => {
|
|
3787
3827
|
const set = listeners.get(key) ?? /* @__PURE__ */ new Set();
|
|
3788
3828
|
listeners.set(key, set);
|
|
3789
|
-
const handler = () => setTick((
|
|
3829
|
+
const handler = () => setTick((t4) => t4 + 1);
|
|
3790
3830
|
set.add(handler);
|
|
3791
3831
|
return () => {
|
|
3792
3832
|
set.delete(handler);
|
|
@@ -3906,7 +3946,7 @@ function ConfigJsonModal({
|
|
|
3906
3946
|
setError(e.message);
|
|
3907
3947
|
}
|
|
3908
3948
|
};
|
|
3909
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "
|
|
3949
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: locale("cfgpanel_json_title"), icon: lucideReact.Code2, iconColor: color, onClose, width: "60vh", maxHeight: "80vh", zIndex: 200, children: [
|
|
3910
3950
|
/* @__PURE__ */ jsxRuntime.jsxs(core.Box, { flex: 1, p: "0.8vh", style: { overflowY: "auto" }, children: [
|
|
3911
3951
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3912
3952
|
core.JsonInput,
|
|
@@ -3934,7 +3974,7 @@ function ConfigJsonModal({
|
|
|
3934
3974
|
style: { background: "transparent", border: `0.1vh solid ${theme.colors.dark[6]}`, borderRadius: theme.radius.xs, padding: `${theme.spacing.xxs} ${theme.spacing.xs}`, cursor: "pointer", display: "flex", alignItems: "center", gap: theme.spacing.xxs },
|
|
3935
3975
|
children: [
|
|
3936
3976
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { color: "rgba(255,255,255,0.4)" }),
|
|
3937
|
-
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: "rgba(255,255,255,0.4)", children: "
|
|
3977
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: "rgba(255,255,255,0.4)", children: locale("cfgpanel_cancel") })
|
|
3938
3978
|
]
|
|
3939
3979
|
}
|
|
3940
3980
|
),
|
|
@@ -3947,7 +3987,7 @@ function ConfigJsonModal({
|
|
|
3947
3987
|
style: { background: core.alpha(color, 0.14), border: `0.1vh solid ${core.alpha(color, 0.4)}`, borderRadius: theme.radius.xs, padding: `${theme.spacing.xxs} ${theme.spacing.xs}`, cursor: "pointer", display: "flex", alignItems: "center", gap: theme.spacing.xxs },
|
|
3948
3988
|
children: [
|
|
3949
3989
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { color }),
|
|
3950
|
-
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: color, children: "
|
|
3990
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: color, children: locale("cfgpanel_apply") })
|
|
3951
3991
|
]
|
|
3952
3992
|
}
|
|
3953
3993
|
)
|
|
@@ -4088,7 +4128,7 @@ function ConfigHistoryModal({
|
|
|
4088
4128
|
historyQuery.fetchNextPage();
|
|
4089
4129
|
}
|
|
4090
4130
|
};
|
|
4091
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "
|
|
4131
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: locale("cfgpanel_history_title"), icon: lucideReact.History, iconColor: color, onClose, width: "88vh", maxHeight: "82vh", zIndex: 260, children: [
|
|
4092
4132
|
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { flex: 1, minHeight: 0 }, children: [
|
|
4093
4133
|
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { gap: "xs", p: "sm", style: { borderBottom: `0.1vh solid ${core.alpha(theme.colors.dark[7], 0.8)}` }, children: [
|
|
4094
4134
|
/* @__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 } }),
|
|
@@ -4131,7 +4171,7 @@ function ConfigHistoryModal({
|
|
|
4131
4171
|
style: { background: "transparent", border: `0.1vh solid ${theme.colors.dark[6]}`, borderRadius: theme.radius.xs, padding: `${theme.spacing.xxs} ${theme.spacing.xs}`, cursor: "pointer", display: "flex", alignItems: "center", gap: theme.spacing.xxs },
|
|
4132
4172
|
children: [
|
|
4133
4173
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { color: "rgba(255,255,255,0.4)", size: "1.5vh" }),
|
|
4134
|
-
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: "rgba(255,255,255,0.4)", children: "
|
|
4174
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: "rgba(255,255,255,0.4)", children: locale("cfgpanel_close") })
|
|
4135
4175
|
]
|
|
4136
4176
|
}
|
|
4137
4177
|
) })
|
|
@@ -4191,9 +4231,9 @@ function ConfigPanelInner({
|
|
|
4191
4231
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: resetOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4192
4232
|
ConfirmModal,
|
|
4193
4233
|
{
|
|
4194
|
-
title: "
|
|
4195
|
-
description: "
|
|
4196
|
-
confirmLabel: "
|
|
4234
|
+
title: locale("cfgpanel_reset_title"),
|
|
4235
|
+
description: locale("cfgpanel_reset_desc"),
|
|
4236
|
+
confirmLabel: locale("cfgpanel_reset_confirm"),
|
|
4197
4237
|
confirmText: resetConfirmText,
|
|
4198
4238
|
onConfirm: async () => {
|
|
4199
4239
|
setResetOpen(false);
|
|
@@ -4225,9 +4265,9 @@ function ConfigPanelInner({
|
|
|
4225
4265
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: pendingAction !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4226
4266
|
ConfirmModal,
|
|
4227
4267
|
{
|
|
4228
|
-
title: "
|
|
4229
|
-
description: pendingAction === "back" ? "
|
|
4230
|
-
confirmLabel: pendingAction === "back" ? "
|
|
4268
|
+
title: locale("cfgpanel_discard_title"),
|
|
4269
|
+
description: pendingAction === "back" ? locale("cfgpanel_discard_desc_back") : locale("cfgpanel_discard_desc_close"),
|
|
4270
|
+
confirmLabel: pendingAction === "back" ? locale("cfgpanel_discard_confirm_back") : locale("cfgpanel_discard_confirm_close"),
|
|
4231
4271
|
onConfirm: () => {
|
|
4232
4272
|
const action = pendingAction;
|
|
4233
4273
|
setPendingAction(null);
|
|
@@ -4265,7 +4305,7 @@ function ConfigPanelInner({
|
|
|
4265
4305
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4266
4306
|
framerMotion.motion.button,
|
|
4267
4307
|
{
|
|
4268
|
-
title: "
|
|
4308
|
+
title: locale("cfgpanel_back_title"),
|
|
4269
4309
|
onClick: handleBack,
|
|
4270
4310
|
whileHover: { background: core.alpha(color, 0.16), borderColor: core.alpha(color, 0.45) },
|
|
4271
4311
|
whileTap: { scale: 0.95 },
|
|
@@ -4293,7 +4333,7 @@ function ConfigPanelInner({
|
|
|
4293
4333
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4294
4334
|
framerMotion.motion.button,
|
|
4295
4335
|
{
|
|
4296
|
-
title: "
|
|
4336
|
+
title: locale("cfgpanel_undo"),
|
|
4297
4337
|
onClick: () => form.canBack && form.back(),
|
|
4298
4338
|
disabled: !form.canBack,
|
|
4299
4339
|
whileHover: form.canBack ? { background: "rgba(255,255,255,0.07)" } : void 0,
|
|
@@ -4305,7 +4345,7 @@ function ConfigPanelInner({
|
|
|
4305
4345
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4306
4346
|
framerMotion.motion.button,
|
|
4307
4347
|
{
|
|
4308
|
-
title: "
|
|
4348
|
+
title: locale("cfgpanel_redo"),
|
|
4309
4349
|
onClick: () => form.canForward && form.forward(),
|
|
4310
4350
|
disabled: !form.canForward,
|
|
4311
4351
|
whileHover: form.canForward ? { background: "rgba(255,255,255,0.07)" } : void 0,
|
|
@@ -4317,7 +4357,7 @@ function ConfigPanelInner({
|
|
|
4317
4357
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4318
4358
|
framerMotion.motion.button,
|
|
4319
4359
|
{
|
|
4320
|
-
title: isSaving ? "
|
|
4360
|
+
title: isSaving ? locale("cfgpanel_saving") : isDirty ? `${locale("cfgpanel_save")} (${changedCount})` : locale("cfgpanel_save"),
|
|
4321
4361
|
onClick: () => isDirty && !isSaving && form.submit(),
|
|
4322
4362
|
disabled: !isDirty || isSaving,
|
|
4323
4363
|
whileHover: isDirty && !isSaving ? { background: core.alpha(color, 0.25), borderColor: core.alpha(color, 0.5) } : void 0,
|
|
@@ -4329,7 +4369,7 @@ function ConfigPanelInner({
|
|
|
4329
4369
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4330
4370
|
framerMotion.motion.button,
|
|
4331
4371
|
{
|
|
4332
|
-
title: "
|
|
4372
|
+
title: locale("cfgpanel_history"),
|
|
4333
4373
|
onClick: () => setHistoryOpen(true),
|
|
4334
4374
|
whileHover: { background: core.alpha("#22d3ee", 0.16), borderColor: core.alpha("#22d3ee", 0.5) },
|
|
4335
4375
|
whileTap: { scale: 0.97 },
|
|
@@ -4350,7 +4390,7 @@ function ConfigPanelInner({
|
|
|
4350
4390
|
style: { width: "100%", background: "transparent", border: `0.1vh solid ${isDirty ? core.alpha("#f97316", 0.35) : core.alpha(theme.colors.dark[5], 0.3)}`, borderRadius: theme.radius.xs, padding: "0.65vh 0.8vh", cursor: isDirty ? "pointer" : "default", display: "flex", alignItems: "center", gap: "0.55vh", opacity: isDirty ? 1 : 0.35, transition: "opacity 0.2s" },
|
|
4351
4391
|
children: [
|
|
4352
4392
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { color: isDirty ? "#f97316" : "rgba(255,255,255,0.35)", size: "1.6vh" }),
|
|
4353
|
-
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: isDirty ? "#f97316" : "rgba(255,255,255,0.35)", children: "
|
|
4393
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: isDirty ? "#f97316" : "rgba(255,255,255,0.35)", children: locale("cfgpanel_discard") })
|
|
4354
4394
|
]
|
|
4355
4395
|
}
|
|
4356
4396
|
),
|
|
@@ -4364,7 +4404,7 @@ function ConfigPanelInner({
|
|
|
4364
4404
|
style: { width: "100%", background: core.alpha(color, 0.07), border: `0.1vh solid ${core.alpha(color, 0.28)}`, borderRadius: theme.radius.xs, padding: "0.65vh 0.8vh", cursor: "pointer", display: "flex", alignItems: "center", gap: "0.55vh" },
|
|
4365
4405
|
children: [
|
|
4366
4406
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code2, { color, size: "1.6vh" }),
|
|
4367
|
-
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: color, children: "
|
|
4407
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: color, children: locale("cfgpanel_manual_edit") })
|
|
4368
4408
|
]
|
|
4369
4409
|
}
|
|
4370
4410
|
),
|
|
@@ -4377,12 +4417,13 @@ function ConfigPanelInner({
|
|
|
4377
4417
|
style: { width: "100%", background: core.alpha("#ef4444", 0.07), border: `0.1vh solid ${core.alpha("#ef4444", 0.25)}`, borderRadius: theme.radius.xs, padding: "0.65vh 0.8vh", cursor: "pointer", display: "flex", alignItems: "center", gap: "0.55vh" },
|
|
4378
4418
|
children: [
|
|
4379
4419
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { color: "#ef4444", size: "1.6vh" }),
|
|
4380
|
-
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: "#ef4444", children: "
|
|
4420
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: "#ef4444", children: locale("cfgpanel_reset_defaults") })
|
|
4381
4421
|
]
|
|
4382
4422
|
}
|
|
4383
4423
|
),
|
|
4384
4424
|
version && /* @__PURE__ */ jsxRuntime.jsxs(core.Text, { size: "0.95vh", c: "dimmed", ta: "center", style: { letterSpacing: "0.04em", opacity: 0.8 }, children: [
|
|
4385
|
-
"
|
|
4425
|
+
locale("cfgpanel_version"),
|
|
4426
|
+
" ",
|
|
4386
4427
|
version
|
|
4387
4428
|
] })
|
|
4388
4429
|
] })
|
|
@@ -5473,24 +5514,6 @@ var MANTINE_COLOR_OPTIONS = [
|
|
|
5473
5514
|
"yellow",
|
|
5474
5515
|
"orange"
|
|
5475
5516
|
].map((value) => ({ value, label: value }));
|
|
5476
|
-
var DEFAULT_PALETTE = [
|
|
5477
|
-
"#f0f4ff",
|
|
5478
|
-
"#d9e3ff",
|
|
5479
|
-
"#bfcfff",
|
|
5480
|
-
"#a6bbff",
|
|
5481
|
-
"#8ca7ff",
|
|
5482
|
-
"#7393ff",
|
|
5483
|
-
"#5a7fff",
|
|
5484
|
-
"#406bff",
|
|
5485
|
-
"#2547ff",
|
|
5486
|
-
"#0b33ff"
|
|
5487
|
-
];
|
|
5488
|
-
var DEFAULT_VALUE = {
|
|
5489
|
-
useOverride: false,
|
|
5490
|
-
primaryColor: "dirk",
|
|
5491
|
-
primaryShade: 5,
|
|
5492
|
-
customTheme: DEFAULT_PALETTE
|
|
5493
|
-
};
|
|
5494
5517
|
function GroupLabel({ label }) {
|
|
5495
5518
|
return /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "xs", mt: "xxs", children: [
|
|
5496
5519
|
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.07em", c: "rgba(255,255,255,0.2)", children: label }),
|
|
@@ -5505,10 +5528,10 @@ function ThemeOverrideSection({
|
|
|
5505
5528
|
const color = mantineTheme.colors[mantineTheme.primaryColor][5];
|
|
5506
5529
|
const raw = useFormField(schemaKey);
|
|
5507
5530
|
const value = {
|
|
5508
|
-
useOverride: raw?.useOverride ??
|
|
5509
|
-
primaryColor: raw?.primaryColor ??
|
|
5510
|
-
primaryShade: raw?.primaryShade ??
|
|
5511
|
-
customTheme: Array.isArray(raw?.customTheme) && raw.customTheme.length === 10 ? raw.customTheme :
|
|
5531
|
+
useOverride: raw?.useOverride ?? defaultThemeOverride.useOverride,
|
|
5532
|
+
primaryColor: raw?.primaryColor ?? defaultThemeOverride.primaryColor,
|
|
5533
|
+
primaryShade: raw?.primaryShade ?? defaultThemeOverride.primaryShade,
|
|
5534
|
+
customTheme: Array.isArray(raw?.customTheme) && raw.customTheme.length === 10 ? raw.customTheme : defaultThemeOverride.customTheme
|
|
5512
5535
|
};
|
|
5513
5536
|
const { setValue } = useFormActions();
|
|
5514
5537
|
const set = (key, val) => setValue(schemaKey, { ...value, [key]: val });
|
|
@@ -5715,6 +5738,403 @@ function SwatchTile({
|
|
|
5715
5738
|
) })
|
|
5716
5739
|
] });
|
|
5717
5740
|
}
|
|
5741
|
+
function usePlayers(opts = {}) {
|
|
5742
|
+
const {
|
|
5743
|
+
includeOffline = false,
|
|
5744
|
+
search = "",
|
|
5745
|
+
limit = 50,
|
|
5746
|
+
staleTimeMs,
|
|
5747
|
+
refetchIntervalMs
|
|
5748
|
+
} = opts;
|
|
5749
|
+
const query = reactQuery.useQuery({
|
|
5750
|
+
queryKey: includeOffline ? ["dirk:players", "search", search.trim().toLowerCase(), limit] : ["dirk:players", "online"],
|
|
5751
|
+
queryFn: async () => {
|
|
5752
|
+
const toolId = includeOffline ? "searchPlayers" : "getOnlinePlayers";
|
|
5753
|
+
const payload = includeOffline ? { id: toolId, value: { search: search.trim(), limit } } : { id: toolId };
|
|
5754
|
+
const result = await fetchNui(
|
|
5755
|
+
"ADMIN_TOOL_QUERY",
|
|
5756
|
+
payload,
|
|
5757
|
+
// Browser-dev fallback. Returns a couple of mock players so the
|
|
5758
|
+
// dev shell isn't blank.
|
|
5759
|
+
includeOffline ? [
|
|
5760
|
+
{ id: 1, citizenId: "ABC12345", name: "Dev User", charName: "John Doe", online: true },
|
|
5761
|
+
{ id: null, citizenId: "DEF67890", name: "", charName: "Jane Offline", online: false }
|
|
5762
|
+
] : [
|
|
5763
|
+
{ id: 1, citizenId: "ABC12345", name: "Dev User", charName: "John Doe", online: true }
|
|
5764
|
+
]
|
|
5765
|
+
);
|
|
5766
|
+
return Array.isArray(result) ? result : [];
|
|
5767
|
+
},
|
|
5768
|
+
staleTime: staleTimeMs ?? (includeOffline ? 3e4 : 5e3),
|
|
5769
|
+
gcTime: 5 * 6e4,
|
|
5770
|
+
refetchInterval: refetchIntervalMs ?? false,
|
|
5771
|
+
refetchOnWindowFocus: false,
|
|
5772
|
+
placeholderData: includeOffline ? reactQuery.keepPreviousData : void 0
|
|
5773
|
+
});
|
|
5774
|
+
return {
|
|
5775
|
+
players: query.data ?? [],
|
|
5776
|
+
isLoading: query.isLoading,
|
|
5777
|
+
isFetching: query.isFetching,
|
|
5778
|
+
error: query.error ?? null,
|
|
5779
|
+
refresh: () => query.refetch()
|
|
5780
|
+
};
|
|
5781
|
+
}
|
|
5782
|
+
var DEBOUNCE_MS = 300;
|
|
5783
|
+
var ONLINE_COLOR = "#3FA83F";
|
|
5784
|
+
var OFFLINE_COLOR = "#E54141";
|
|
5785
|
+
function PlayerSelect({
|
|
5786
|
+
value,
|
|
5787
|
+
onChange,
|
|
5788
|
+
includeOffline = false,
|
|
5789
|
+
limit = 50,
|
|
5790
|
+
searchable: searchableProp,
|
|
5791
|
+
placeholder,
|
|
5792
|
+
nothingFoundMessage: nothingFoundMessageProp,
|
|
5793
|
+
loadingLabel = "Loading\u2026",
|
|
5794
|
+
onlineLabel = "Online",
|
|
5795
|
+
offlineLabel = "Offline",
|
|
5796
|
+
refreshLabel = "Refresh player list",
|
|
5797
|
+
...rest
|
|
5798
|
+
}) {
|
|
5799
|
+
const theme = core.useMantineTheme();
|
|
5800
|
+
const color = theme.colors[theme.primaryColor][5];
|
|
5801
|
+
const [searchInput, setSearchInput] = react.useState("");
|
|
5802
|
+
const [debouncedSearch, setDebouncedSearch] = react.useState("");
|
|
5803
|
+
const { players, isFetching, refresh } = usePlayers({
|
|
5804
|
+
includeOffline,
|
|
5805
|
+
search: includeOffline ? debouncedSearch : void 0,
|
|
5806
|
+
limit
|
|
5807
|
+
});
|
|
5808
|
+
const sortedPlayers = react.useMemo(
|
|
5809
|
+
() => [...players].sort((a, b) => {
|
|
5810
|
+
if (a.online !== b.online) return a.online ? -1 : 1;
|
|
5811
|
+
return a.charName.localeCompare(b.charName);
|
|
5812
|
+
}),
|
|
5813
|
+
[players]
|
|
5814
|
+
);
|
|
5815
|
+
const playerByCitizen = react.useMemo(() => {
|
|
5816
|
+
const m = /* @__PURE__ */ new Map();
|
|
5817
|
+
for (const p of sortedPlayers) m.set(p.citizenId, p);
|
|
5818
|
+
return m;
|
|
5819
|
+
}, [sortedPlayers]);
|
|
5820
|
+
const data = react.useMemo(() => {
|
|
5821
|
+
const items = sortedPlayers.map((p) => ({
|
|
5822
|
+
value: p.citizenId,
|
|
5823
|
+
label: formatLabel(p)
|
|
5824
|
+
}));
|
|
5825
|
+
if (value && !items.some((i) => i.value === value)) {
|
|
5826
|
+
items.unshift({ value, label: value });
|
|
5827
|
+
}
|
|
5828
|
+
return items;
|
|
5829
|
+
}, [sortedPlayers, value]);
|
|
5830
|
+
const selectedPlayer = value ? playerByCitizen.get(value) ?? null : null;
|
|
5831
|
+
const selectedLabel = selectedPlayer ? formatLabel(selectedPlayer) : null;
|
|
5832
|
+
react.useEffect(() => {
|
|
5833
|
+
if (!includeOffline) return;
|
|
5834
|
+
if (selectedLabel && searchInput === selectedLabel) return;
|
|
5835
|
+
const t4 = setTimeout(() => setDebouncedSearch(searchInput), DEBOUNCE_MS);
|
|
5836
|
+
return () => clearTimeout(t4);
|
|
5837
|
+
}, [searchInput, includeOffline, selectedLabel]);
|
|
5838
|
+
const renderOption = ({ option }) => {
|
|
5839
|
+
const p = playerByCitizen.get(option.value);
|
|
5840
|
+
if (!p) return option.label;
|
|
5841
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(core.Group, { justify: "space-between", wrap: "nowrap", gap: "xs", style: { width: "100%" }, children: [
|
|
5842
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { size: "xs", truncate: true, style: { flex: 1 }, children: formatLabel(p) }),
|
|
5843
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusDot, { online: p.online, onlineLabel, offlineLabel })
|
|
5844
|
+
] });
|
|
5845
|
+
};
|
|
5846
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5847
|
+
core.Select,
|
|
5848
|
+
{
|
|
5849
|
+
...rest,
|
|
5850
|
+
data,
|
|
5851
|
+
value: value ?? null,
|
|
5852
|
+
onChange: (v) => {
|
|
5853
|
+
if (!v) return onChange(null);
|
|
5854
|
+
const player = playerByCitizen.get(v) ?? null;
|
|
5855
|
+
onChange(player);
|
|
5856
|
+
},
|
|
5857
|
+
searchable: searchableProp ?? true,
|
|
5858
|
+
searchValue: includeOffline ? searchInput : void 0,
|
|
5859
|
+
onSearchChange: includeOffline ? setSearchInput : void 0,
|
|
5860
|
+
placeholder,
|
|
5861
|
+
nothingFoundMessage: isFetching ? loadingLabel : nothingFoundMessageProp ?? "No players found",
|
|
5862
|
+
maxDropdownHeight: 300,
|
|
5863
|
+
renderOption,
|
|
5864
|
+
leftSection: selectedPlayer ? /* @__PURE__ */ jsxRuntime.jsx(StatusDot, { online: selectedPlayer.online, onlineLabel, offlineLabel }) : void 0,
|
|
5865
|
+
rightSectionWidth: "3.5vh",
|
|
5866
|
+
rightSectionPointerEvents: "all",
|
|
5867
|
+
rightSection: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5868
|
+
core.ActionIcon,
|
|
5869
|
+
{
|
|
5870
|
+
variant: "subtle",
|
|
5871
|
+
size: "sm",
|
|
5872
|
+
onClick: (e) => {
|
|
5873
|
+
e.stopPropagation();
|
|
5874
|
+
refresh();
|
|
5875
|
+
},
|
|
5876
|
+
"aria-label": refreshLabel,
|
|
5877
|
+
title: refreshLabel,
|
|
5878
|
+
style: { marginRight: "0.6vh" },
|
|
5879
|
+
children: isFetching ? /* @__PURE__ */ jsxRuntime.jsx(core.Loader, { size: "1.2vh", color }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { size: "1.4vh", color })
|
|
5880
|
+
}
|
|
5881
|
+
)
|
|
5882
|
+
}
|
|
5883
|
+
);
|
|
5884
|
+
}
|
|
5885
|
+
function StatusDot({ online, onlineLabel, offlineLabel }) {
|
|
5886
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5887
|
+
"span",
|
|
5888
|
+
{
|
|
5889
|
+
title: online ? onlineLabel : offlineLabel,
|
|
5890
|
+
style: {
|
|
5891
|
+
display: "inline-block",
|
|
5892
|
+
width: "0.9vh",
|
|
5893
|
+
height: "0.9vh",
|
|
5894
|
+
borderRadius: "50%",
|
|
5895
|
+
backgroundColor: online ? ONLINE_COLOR : OFFLINE_COLOR,
|
|
5896
|
+
boxShadow: `0 0 0.4vh ${online ? ONLINE_COLOR : OFFLINE_COLOR}`,
|
|
5897
|
+
flexShrink: 0
|
|
5898
|
+
}
|
|
5899
|
+
}
|
|
5900
|
+
);
|
|
5901
|
+
}
|
|
5902
|
+
function formatLabel(p) {
|
|
5903
|
+
const parts = [p.charName || p.citizenId];
|
|
5904
|
+
if (p.online) {
|
|
5905
|
+
if (p.name) parts.push(p.name);
|
|
5906
|
+
if (p.id != null) parts.push(`#${p.id}`);
|
|
5907
|
+
}
|
|
5908
|
+
return parts.join(" \xB7 ");
|
|
5909
|
+
}
|
|
5910
|
+
var t = (key, fallback) => {
|
|
5911
|
+
const v = locale(key);
|
|
5912
|
+
return v === key ? fallback : v;
|
|
5913
|
+
};
|
|
5914
|
+
var DEFAULT_VALUE = {
|
|
5915
|
+
groups: [],
|
|
5916
|
+
identifiers: []
|
|
5917
|
+
};
|
|
5918
|
+
function SectionLabel({ icon: Icon, label }) {
|
|
5919
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "xs", mt: "xs", children: [
|
|
5920
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { size: "1.4vh", color: "rgba(255,255,255,0.3)" }),
|
|
5921
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.07em", c: "rgba(255,255,255,0.2)", children: label }),
|
|
5922
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, height: "0.05vh", background: "rgba(255,255,255,0.06)" } })
|
|
5923
|
+
] });
|
|
5924
|
+
}
|
|
5925
|
+
function EmptyHint({ text }) {
|
|
5926
|
+
return /* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.25)", ta: "center", py: "xs", children: text });
|
|
5927
|
+
}
|
|
5928
|
+
function AccessOverrideSection({
|
|
5929
|
+
schemaKey = "access",
|
|
5930
|
+
title,
|
|
5931
|
+
description,
|
|
5932
|
+
groupType,
|
|
5933
|
+
includeOffline = true
|
|
5934
|
+
}) {
|
|
5935
|
+
const mantineTheme = core.useMantineTheme();
|
|
5936
|
+
const color = mantineTheme.colors[mantineTheme.primaryColor][5];
|
|
5937
|
+
const raw = useFormField(schemaKey);
|
|
5938
|
+
const value = {
|
|
5939
|
+
groups: Array.isArray(raw?.groups) ? raw.groups : DEFAULT_VALUE.groups,
|
|
5940
|
+
identifiers: Array.isArray(raw?.identifiers) ? raw.identifiers : DEFAULT_VALUE.identifiers
|
|
5941
|
+
};
|
|
5942
|
+
const { setValue } = useFormActions();
|
|
5943
|
+
const set = (key, val) => setValue(schemaKey, { ...value, [key]: val });
|
|
5944
|
+
const [addingGroup, setAddingGroup] = react.useState(false);
|
|
5945
|
+
const [addingPlayer, setAddingPlayer] = react.useState(false);
|
|
5946
|
+
const commitGroup = (name) => {
|
|
5947
|
+
if (!name) return;
|
|
5948
|
+
set("groups", [...value.groups, name]);
|
|
5949
|
+
setAddingGroup(false);
|
|
5950
|
+
};
|
|
5951
|
+
const setGroup = (index, name) => {
|
|
5952
|
+
const next = [...value.groups];
|
|
5953
|
+
next[index] = name;
|
|
5954
|
+
set("groups", next.filter((g) => g !== ""));
|
|
5955
|
+
};
|
|
5956
|
+
const removeGroup = (index) => set("groups", value.groups.filter((_, i) => i !== index));
|
|
5957
|
+
const commitIdentifier = (id) => {
|
|
5958
|
+
if (!id) return;
|
|
5959
|
+
set("identifiers", [...value.identifiers, id]);
|
|
5960
|
+
setAddingPlayer(false);
|
|
5961
|
+
};
|
|
5962
|
+
const setIdentifier = (index, id) => {
|
|
5963
|
+
const next = [...value.identifiers];
|
|
5964
|
+
next[index] = id;
|
|
5965
|
+
set("identifiers", next.filter((x) => x !== ""));
|
|
5966
|
+
};
|
|
5967
|
+
const removeIdentifier = (index) => set("identifiers", value.identifiers.filter((_, i) => i !== index));
|
|
5968
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5969
|
+
core.Flex,
|
|
5970
|
+
{
|
|
5971
|
+
direction: "column",
|
|
5972
|
+
gap: "xs",
|
|
5973
|
+
p: "sm",
|
|
5974
|
+
style: { flex: 1, minHeight: 0, overflowY: "auto" },
|
|
5975
|
+
children: [
|
|
5976
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5977
|
+
AdminPageTitle,
|
|
5978
|
+
{
|
|
5979
|
+
icon: lucideReact.ShieldCheck,
|
|
5980
|
+
title: title || t("Access", "Access"),
|
|
5981
|
+
color
|
|
5982
|
+
}
|
|
5983
|
+
),
|
|
5984
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.4)", children: description || t(
|
|
5985
|
+
"AccessOverrideDesc",
|
|
5986
|
+
"Grant access to this resource's admin panel to specific groups and players, in addition to your global dirk_lib admins. Enforcement is server-side."
|
|
5987
|
+
) }),
|
|
5988
|
+
/* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { icon: lucideReact.Users, label: t("AccessGroups", "Groups") }),
|
|
5989
|
+
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", gap: "xxs", children: [
|
|
5990
|
+
value.groups.length === 0 && !addingGroup && /* @__PURE__ */ jsxRuntime.jsx(EmptyHint, { text: t("AccessNoGroups", "No groups added.") }),
|
|
5991
|
+
value.groups.map((name, i) => /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "xs", children: [
|
|
5992
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5993
|
+
GroupName,
|
|
5994
|
+
{
|
|
5995
|
+
value: name,
|
|
5996
|
+
onChange: (v) => setGroup(i, v),
|
|
5997
|
+
type: groupType,
|
|
5998
|
+
placeholder: t("AccessPickGroup", "Pick a group\u2026"),
|
|
5999
|
+
style: { flex: 1 }
|
|
6000
|
+
}
|
|
6001
|
+
),
|
|
6002
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6003
|
+
core.ActionIcon,
|
|
6004
|
+
{
|
|
6005
|
+
variant: "subtle",
|
|
6006
|
+
color: "red",
|
|
6007
|
+
size: "md",
|
|
6008
|
+
onClick: () => removeGroup(i),
|
|
6009
|
+
title: t("Remove", "Remove"),
|
|
6010
|
+
"aria-label": t("Remove", "Remove"),
|
|
6011
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { size: "1.4vh" })
|
|
6012
|
+
}
|
|
6013
|
+
)
|
|
6014
|
+
] }, i)),
|
|
6015
|
+
addingGroup && /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "xs", children: [
|
|
6016
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6017
|
+
GroupName,
|
|
6018
|
+
{
|
|
6019
|
+
value: "",
|
|
6020
|
+
onChange: (v) => commitGroup(v),
|
|
6021
|
+
type: groupType,
|
|
6022
|
+
placeholder: t("AccessPickGroup", "Pick a group\u2026"),
|
|
6023
|
+
style: { flex: 1 }
|
|
6024
|
+
}
|
|
6025
|
+
),
|
|
6026
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6027
|
+
core.ActionIcon,
|
|
6028
|
+
{
|
|
6029
|
+
variant: "subtle",
|
|
6030
|
+
color: "red",
|
|
6031
|
+
size: "md",
|
|
6032
|
+
onClick: () => setAddingGroup(false),
|
|
6033
|
+
title: t("Remove", "Remove"),
|
|
6034
|
+
"aria-label": t("Remove", "Remove"),
|
|
6035
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { size: "1.4vh" })
|
|
6036
|
+
}
|
|
6037
|
+
)
|
|
6038
|
+
] })
|
|
6039
|
+
] }),
|
|
6040
|
+
!addingGroup && /* @__PURE__ */ jsxRuntime.jsx(AddRowButton, { label: t("AccessAddGroup", "Add group"), onClick: () => setAddingGroup(true) }),
|
|
6041
|
+
/* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { icon: lucideReact.UserRound, label: t("AccessPlayers", "Players") }),
|
|
6042
|
+
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", gap: "xxs", children: [
|
|
6043
|
+
value.identifiers.length === 0 && !addingPlayer && /* @__PURE__ */ jsxRuntime.jsx(EmptyHint, { text: t("AccessNoPlayers", "No players added.") }),
|
|
6044
|
+
value.identifiers.map((id, i) => /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "xs", children: [
|
|
6045
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6046
|
+
PlayerSelect,
|
|
6047
|
+
{
|
|
6048
|
+
value: id || null,
|
|
6049
|
+
onChange: (p) => setIdentifier(i, p?.citizenId ?? ""),
|
|
6050
|
+
includeOffline,
|
|
6051
|
+
placeholder: t("AccessPickPlayer", "Pick a player\u2026"),
|
|
6052
|
+
style: { flex: 1 },
|
|
6053
|
+
size: "xs"
|
|
6054
|
+
}
|
|
6055
|
+
),
|
|
6056
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6057
|
+
core.ActionIcon,
|
|
6058
|
+
{
|
|
6059
|
+
variant: "subtle",
|
|
6060
|
+
color: "red",
|
|
6061
|
+
size: "md",
|
|
6062
|
+
onClick: () => removeIdentifier(i),
|
|
6063
|
+
title: t("Remove", "Remove"),
|
|
6064
|
+
"aria-label": t("Remove", "Remove"),
|
|
6065
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { size: "1.4vh" })
|
|
6066
|
+
}
|
|
6067
|
+
)
|
|
6068
|
+
] }, i)),
|
|
6069
|
+
addingPlayer && /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "xs", children: [
|
|
6070
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6071
|
+
PlayerSelect,
|
|
6072
|
+
{
|
|
6073
|
+
value: null,
|
|
6074
|
+
onChange: (p) => commitIdentifier(p?.citizenId ?? ""),
|
|
6075
|
+
includeOffline,
|
|
6076
|
+
placeholder: t("AccessPickPlayer", "Pick a player\u2026"),
|
|
6077
|
+
style: { flex: 1 },
|
|
6078
|
+
size: "xs"
|
|
6079
|
+
}
|
|
6080
|
+
),
|
|
6081
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6082
|
+
core.ActionIcon,
|
|
6083
|
+
{
|
|
6084
|
+
variant: "subtle",
|
|
6085
|
+
color: "red",
|
|
6086
|
+
size: "md",
|
|
6087
|
+
onClick: () => setAddingPlayer(false),
|
|
6088
|
+
title: t("Remove", "Remove"),
|
|
6089
|
+
"aria-label": t("Remove", "Remove"),
|
|
6090
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { size: "1.4vh" })
|
|
6091
|
+
}
|
|
6092
|
+
)
|
|
6093
|
+
] })
|
|
6094
|
+
] }),
|
|
6095
|
+
!addingPlayer && /* @__PURE__ */ jsxRuntime.jsx(AddRowButton, { label: t("AccessAddPlayer", "Add player"), onClick: () => setAddingPlayer(true) })
|
|
6096
|
+
]
|
|
6097
|
+
}
|
|
6098
|
+
);
|
|
6099
|
+
}
|
|
6100
|
+
function AddRowButton({ label, onClick }) {
|
|
6101
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6102
|
+
core.Flex,
|
|
6103
|
+
{
|
|
6104
|
+
align: "center",
|
|
6105
|
+
justify: "center",
|
|
6106
|
+
gap: "xs",
|
|
6107
|
+
onClick,
|
|
6108
|
+
role: "button",
|
|
6109
|
+
tabIndex: 0,
|
|
6110
|
+
onKeyDown: (e) => {
|
|
6111
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
6112
|
+
e.preventDefault();
|
|
6113
|
+
onClick();
|
|
6114
|
+
}
|
|
6115
|
+
},
|
|
6116
|
+
py: "xs",
|
|
6117
|
+
style: {
|
|
6118
|
+
cursor: "pointer",
|
|
6119
|
+
border: "0.1vh dashed rgba(255,255,255,0.12)",
|
|
6120
|
+
borderRadius: "0.4vh",
|
|
6121
|
+
transition: "background 0.15s, border-color 0.15s"
|
|
6122
|
+
},
|
|
6123
|
+
onMouseEnter: (e) => {
|
|
6124
|
+
e.currentTarget.style.background = "rgba(255,255,255,0.03)";
|
|
6125
|
+
e.currentTarget.style.borderColor = "rgba(255,255,255,0.2)";
|
|
6126
|
+
},
|
|
6127
|
+
onMouseLeave: (e) => {
|
|
6128
|
+
e.currentTarget.style.background = "transparent";
|
|
6129
|
+
e.currentTarget.style.borderColor = "rgba(255,255,255,0.12)";
|
|
6130
|
+
},
|
|
6131
|
+
children: [
|
|
6132
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { size: "1.4vh", color: "rgba(255,255,255,0.4)" }),
|
|
6133
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: "rgba(255,255,255,0.4)", children: label })
|
|
6134
|
+
]
|
|
6135
|
+
}
|
|
6136
|
+
);
|
|
6137
|
+
}
|
|
5718
6138
|
|
|
5719
6139
|
// src/utils/gtaAnimPostFx.ts
|
|
5720
6140
|
var GTA_ANIM_POST_FX_GROUP_ORDER = [
|
|
@@ -6304,7 +6724,7 @@ function ScenarioSelect({
|
|
|
6304
6724
|
}
|
|
6305
6725
|
);
|
|
6306
6726
|
}
|
|
6307
|
-
var
|
|
6727
|
+
var t2 = (key, fallback) => {
|
|
6308
6728
|
const v = locale(key);
|
|
6309
6729
|
return v === key ? fallback : v;
|
|
6310
6730
|
};
|
|
@@ -6372,7 +6792,7 @@ function DiscordRoleSelect(props) {
|
|
|
6372
6792
|
return map;
|
|
6373
6793
|
}, [roles]);
|
|
6374
6794
|
if (errorCode === "NotConfigured") {
|
|
6375
|
-
const notConfiguredPlaceholder =
|
|
6795
|
+
const notConfiguredPlaceholder = t2(
|
|
6376
6796
|
"DiscordNotConfigured",
|
|
6377
6797
|
"Not configured \u2014 set in /dirk_lib"
|
|
6378
6798
|
);
|
|
@@ -6440,9 +6860,9 @@ function DiscordRoleSelect(props) {
|
|
|
6440
6860
|
e.stopPropagation();
|
|
6441
6861
|
refresh();
|
|
6442
6862
|
},
|
|
6443
|
-
title:
|
|
6863
|
+
title: t2("Refresh", "Refresh"),
|
|
6444
6864
|
loading,
|
|
6445
|
-
"aria-label":
|
|
6865
|
+
"aria-label": t2("Refresh", "Refresh"),
|
|
6446
6866
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { size: "1.2vh" })
|
|
6447
6867
|
}
|
|
6448
6868
|
);
|
|
@@ -6452,7 +6872,7 @@ function DiscordRoleSelect(props) {
|
|
|
6452
6872
|
{
|
|
6453
6873
|
label,
|
|
6454
6874
|
size,
|
|
6455
|
-
placeholder: placeholder ||
|
|
6875
|
+
placeholder: placeholder || t2("PickRoles", "Pick roles..."),
|
|
6456
6876
|
data,
|
|
6457
6877
|
value: props.value || [],
|
|
6458
6878
|
onChange: (ids) => props.onChange(ids),
|
|
@@ -6464,7 +6884,7 @@ function DiscordRoleSelect(props) {
|
|
|
6464
6884
|
rightSectionPointerEvents: "all",
|
|
6465
6885
|
style,
|
|
6466
6886
|
styles,
|
|
6467
|
-
nothingFoundMessage: errorCode ? `${
|
|
6887
|
+
nothingFoundMessage: errorCode ? `${t2("Error", "Error")} (${errorCode})` : t2("NoRoles", "No roles found")
|
|
6468
6888
|
}
|
|
6469
6889
|
);
|
|
6470
6890
|
}
|
|
@@ -6473,7 +6893,7 @@ function DiscordRoleSelect(props) {
|
|
|
6473
6893
|
{
|
|
6474
6894
|
label,
|
|
6475
6895
|
size,
|
|
6476
|
-
placeholder: placeholder ||
|
|
6896
|
+
placeholder: placeholder || t2("PickRole", "Pick a role..."),
|
|
6477
6897
|
data,
|
|
6478
6898
|
value: props.value || null,
|
|
6479
6899
|
onChange: (id) => props.onChange(id),
|
|
@@ -6485,11 +6905,11 @@ function DiscordRoleSelect(props) {
|
|
|
6485
6905
|
rightSectionPointerEvents: "all",
|
|
6486
6906
|
style,
|
|
6487
6907
|
styles,
|
|
6488
|
-
nothingFoundMessage: errorCode ? `${
|
|
6908
|
+
nothingFoundMessage: errorCode ? `${t2("Error", "Error")} (${errorCode})` : t2("NoRoles", "No roles found")
|
|
6489
6909
|
}
|
|
6490
6910
|
);
|
|
6491
6911
|
}
|
|
6492
|
-
var
|
|
6912
|
+
var t3 = (key, fallback) => {
|
|
6493
6913
|
const v = locale(key);
|
|
6494
6914
|
return v === key ? fallback : v;
|
|
6495
6915
|
};
|
|
@@ -6510,7 +6930,7 @@ function FrameworkHint({ framework }) {
|
|
|
6510
6930
|
const theme = core.useMantineTheme();
|
|
6511
6931
|
if (!framework) return null;
|
|
6512
6932
|
const hintKey = `AccountFrameworkHint_${framework}`;
|
|
6513
|
-
const text =
|
|
6933
|
+
const text = t3(hintKey, FRAMEWORK_HINTS[framework] || FRAMEWORK_HINTS.unknown);
|
|
6514
6934
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6515
6935
|
core.Flex,
|
|
6516
6936
|
{
|
|
@@ -6594,9 +7014,9 @@ function AccountSelect(props) {
|
|
|
6594
7014
|
e.stopPropagation();
|
|
6595
7015
|
refresh();
|
|
6596
7016
|
},
|
|
6597
|
-
title:
|
|
7017
|
+
title: t3("Refresh", "Refresh"),
|
|
6598
7018
|
loading,
|
|
6599
|
-
"aria-label":
|
|
7019
|
+
"aria-label": t3("Refresh", "Refresh"),
|
|
6600
7020
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { size: "1.2vh" })
|
|
6601
7021
|
}
|
|
6602
7022
|
);
|
|
@@ -6610,14 +7030,14 @@ function AccountSelect(props) {
|
|
|
6610
7030
|
rightSection: refreshButton,
|
|
6611
7031
|
rightSectionPointerEvents: "all",
|
|
6612
7032
|
style,
|
|
6613
|
-
nothingFoundMessage:
|
|
7033
|
+
nothingFoundMessage: t3("NoAccounts", "No accounts available")
|
|
6614
7034
|
};
|
|
6615
7035
|
return /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", gap: "0.3vh", style, children: [
|
|
6616
7036
|
props.multi ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
6617
7037
|
core.MultiSelect,
|
|
6618
7038
|
{
|
|
6619
7039
|
...sharedSelectProps,
|
|
6620
|
-
placeholder: placeholder ||
|
|
7040
|
+
placeholder: placeholder || t3("PickAccounts", "Pick accounts (or type custom)..."),
|
|
6621
7041
|
value: props.value || [],
|
|
6622
7042
|
onChange: (names) => props.onChange(names),
|
|
6623
7043
|
renderOption,
|
|
@@ -6629,7 +7049,7 @@ function AccountSelect(props) {
|
|
|
6629
7049
|
core.Select,
|
|
6630
7050
|
{
|
|
6631
7051
|
...sharedSelectProps,
|
|
6632
|
-
placeholder: placeholder ||
|
|
7052
|
+
placeholder: placeholder || t3("PickAccount", "Pick an account..."),
|
|
6633
7053
|
value: props.value || null,
|
|
6634
7054
|
onChange: (name) => props.onChange(name),
|
|
6635
7055
|
renderOption,
|
|
@@ -6921,175 +7341,6 @@ function WorldPositionGotoButton2({
|
|
|
6921
7341
|
}
|
|
6922
7342
|
) });
|
|
6923
7343
|
}
|
|
6924
|
-
function usePlayers(opts = {}) {
|
|
6925
|
-
const {
|
|
6926
|
-
includeOffline = false,
|
|
6927
|
-
search = "",
|
|
6928
|
-
limit = 50,
|
|
6929
|
-
staleTimeMs,
|
|
6930
|
-
refetchIntervalMs
|
|
6931
|
-
} = opts;
|
|
6932
|
-
const query = reactQuery.useQuery({
|
|
6933
|
-
queryKey: includeOffline ? ["dirk:players", "search", search.trim().toLowerCase(), limit] : ["dirk:players", "online"],
|
|
6934
|
-
queryFn: async () => {
|
|
6935
|
-
const toolId = includeOffline ? "searchPlayers" : "getOnlinePlayers";
|
|
6936
|
-
const payload = includeOffline ? { id: toolId, value: { search: search.trim(), limit } } : { id: toolId };
|
|
6937
|
-
const result = await fetchNui(
|
|
6938
|
-
"ADMIN_TOOL_QUERY",
|
|
6939
|
-
payload,
|
|
6940
|
-
// Browser-dev fallback. Returns a couple of mock players so the
|
|
6941
|
-
// dev shell isn't blank.
|
|
6942
|
-
includeOffline ? [
|
|
6943
|
-
{ id: 1, citizenId: "ABC12345", name: "Dev User", charName: "John Doe", online: true },
|
|
6944
|
-
{ id: null, citizenId: "DEF67890", name: "", charName: "Jane Offline", online: false }
|
|
6945
|
-
] : [
|
|
6946
|
-
{ id: 1, citizenId: "ABC12345", name: "Dev User", charName: "John Doe", online: true }
|
|
6947
|
-
]
|
|
6948
|
-
);
|
|
6949
|
-
return Array.isArray(result) ? result : [];
|
|
6950
|
-
},
|
|
6951
|
-
staleTime: staleTimeMs ?? (includeOffline ? 3e4 : 5e3),
|
|
6952
|
-
gcTime: 5 * 6e4,
|
|
6953
|
-
refetchInterval: refetchIntervalMs ?? false,
|
|
6954
|
-
refetchOnWindowFocus: false,
|
|
6955
|
-
placeholderData: includeOffline ? reactQuery.keepPreviousData : void 0
|
|
6956
|
-
});
|
|
6957
|
-
return {
|
|
6958
|
-
players: query.data ?? [],
|
|
6959
|
-
isLoading: query.isLoading,
|
|
6960
|
-
isFetching: query.isFetching,
|
|
6961
|
-
error: query.error ?? null,
|
|
6962
|
-
refresh: () => query.refetch()
|
|
6963
|
-
};
|
|
6964
|
-
}
|
|
6965
|
-
var DEBOUNCE_MS = 300;
|
|
6966
|
-
var ONLINE_COLOR = "#3FA83F";
|
|
6967
|
-
var OFFLINE_COLOR = "#E54141";
|
|
6968
|
-
function PlayerSelect({
|
|
6969
|
-
value,
|
|
6970
|
-
onChange,
|
|
6971
|
-
includeOffline = false,
|
|
6972
|
-
limit = 50,
|
|
6973
|
-
searchable: searchableProp,
|
|
6974
|
-
placeholder,
|
|
6975
|
-
nothingFoundMessage: nothingFoundMessageProp,
|
|
6976
|
-
loadingLabel = "Loading\u2026",
|
|
6977
|
-
onlineLabel = "Online",
|
|
6978
|
-
offlineLabel = "Offline",
|
|
6979
|
-
refreshLabel = "Refresh player list",
|
|
6980
|
-
...rest
|
|
6981
|
-
}) {
|
|
6982
|
-
const theme = core.useMantineTheme();
|
|
6983
|
-
const color = theme.colors[theme.primaryColor][5];
|
|
6984
|
-
const [searchInput, setSearchInput] = react.useState("");
|
|
6985
|
-
const [debouncedSearch, setDebouncedSearch] = react.useState("");
|
|
6986
|
-
const { players, isFetching, refresh } = usePlayers({
|
|
6987
|
-
includeOffline,
|
|
6988
|
-
search: includeOffline ? debouncedSearch : void 0,
|
|
6989
|
-
limit
|
|
6990
|
-
});
|
|
6991
|
-
const sortedPlayers = react.useMemo(
|
|
6992
|
-
() => [...players].sort((a, b) => {
|
|
6993
|
-
if (a.online !== b.online) return a.online ? -1 : 1;
|
|
6994
|
-
return a.charName.localeCompare(b.charName);
|
|
6995
|
-
}),
|
|
6996
|
-
[players]
|
|
6997
|
-
);
|
|
6998
|
-
const playerByCitizen = react.useMemo(() => {
|
|
6999
|
-
const m = /* @__PURE__ */ new Map();
|
|
7000
|
-
for (const p of sortedPlayers) m.set(p.citizenId, p);
|
|
7001
|
-
return m;
|
|
7002
|
-
}, [sortedPlayers]);
|
|
7003
|
-
const data = react.useMemo(() => {
|
|
7004
|
-
const items = sortedPlayers.map((p) => ({
|
|
7005
|
-
value: p.citizenId,
|
|
7006
|
-
label: formatLabel(p)
|
|
7007
|
-
}));
|
|
7008
|
-
if (value && !items.some((i) => i.value === value)) {
|
|
7009
|
-
items.unshift({ value, label: value });
|
|
7010
|
-
}
|
|
7011
|
-
return items;
|
|
7012
|
-
}, [sortedPlayers, value]);
|
|
7013
|
-
const selectedPlayer = value ? playerByCitizen.get(value) ?? null : null;
|
|
7014
|
-
const selectedLabel = selectedPlayer ? formatLabel(selectedPlayer) : null;
|
|
7015
|
-
react.useEffect(() => {
|
|
7016
|
-
if (!includeOffline) return;
|
|
7017
|
-
if (selectedLabel && searchInput === selectedLabel) return;
|
|
7018
|
-
const t3 = setTimeout(() => setDebouncedSearch(searchInput), DEBOUNCE_MS);
|
|
7019
|
-
return () => clearTimeout(t3);
|
|
7020
|
-
}, [searchInput, includeOffline, selectedLabel]);
|
|
7021
|
-
const renderOption = ({ option }) => {
|
|
7022
|
-
const p = playerByCitizen.get(option.value);
|
|
7023
|
-
if (!p) return option.label;
|
|
7024
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(core.Group, { justify: "space-between", wrap: "nowrap", gap: "xs", style: { width: "100%" }, children: [
|
|
7025
|
-
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { size: "xs", truncate: true, style: { flex: 1 }, children: formatLabel(p) }),
|
|
7026
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatusDot, { online: p.online, onlineLabel, offlineLabel })
|
|
7027
|
-
] });
|
|
7028
|
-
};
|
|
7029
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7030
|
-
core.Select,
|
|
7031
|
-
{
|
|
7032
|
-
...rest,
|
|
7033
|
-
data,
|
|
7034
|
-
value: value ?? null,
|
|
7035
|
-
onChange: (v) => {
|
|
7036
|
-
if (!v) return onChange(null);
|
|
7037
|
-
const player = playerByCitizen.get(v) ?? null;
|
|
7038
|
-
onChange(player);
|
|
7039
|
-
},
|
|
7040
|
-
searchable: searchableProp ?? true,
|
|
7041
|
-
searchValue: includeOffline ? searchInput : void 0,
|
|
7042
|
-
onSearchChange: includeOffline ? setSearchInput : void 0,
|
|
7043
|
-
placeholder,
|
|
7044
|
-
nothingFoundMessage: isFetching ? loadingLabel : nothingFoundMessageProp ?? "No players found",
|
|
7045
|
-
maxDropdownHeight: 300,
|
|
7046
|
-
renderOption,
|
|
7047
|
-
leftSection: selectedPlayer ? /* @__PURE__ */ jsxRuntime.jsx(StatusDot, { online: selectedPlayer.online, onlineLabel, offlineLabel }) : void 0,
|
|
7048
|
-
rightSectionWidth: "3.5vh",
|
|
7049
|
-
rightSectionPointerEvents: "all",
|
|
7050
|
-
rightSection: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7051
|
-
core.ActionIcon,
|
|
7052
|
-
{
|
|
7053
|
-
variant: "subtle",
|
|
7054
|
-
size: "sm",
|
|
7055
|
-
onClick: (e) => {
|
|
7056
|
-
e.stopPropagation();
|
|
7057
|
-
refresh();
|
|
7058
|
-
},
|
|
7059
|
-
"aria-label": refreshLabel,
|
|
7060
|
-
title: refreshLabel,
|
|
7061
|
-
style: { marginRight: "0.6vh" },
|
|
7062
|
-
children: isFetching ? /* @__PURE__ */ jsxRuntime.jsx(core.Loader, { size: "1.2vh", color }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { size: "1.4vh", color })
|
|
7063
|
-
}
|
|
7064
|
-
)
|
|
7065
|
-
}
|
|
7066
|
-
);
|
|
7067
|
-
}
|
|
7068
|
-
function StatusDot({ online, onlineLabel, offlineLabel }) {
|
|
7069
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7070
|
-
"span",
|
|
7071
|
-
{
|
|
7072
|
-
title: online ? onlineLabel : offlineLabel,
|
|
7073
|
-
style: {
|
|
7074
|
-
display: "inline-block",
|
|
7075
|
-
width: "0.9vh",
|
|
7076
|
-
height: "0.9vh",
|
|
7077
|
-
borderRadius: "50%",
|
|
7078
|
-
backgroundColor: online ? ONLINE_COLOR : OFFLINE_COLOR,
|
|
7079
|
-
boxShadow: `0 0 0.4vh ${online ? ONLINE_COLOR : OFFLINE_COLOR}`,
|
|
7080
|
-
flexShrink: 0
|
|
7081
|
-
}
|
|
7082
|
-
}
|
|
7083
|
-
);
|
|
7084
|
-
}
|
|
7085
|
-
function formatLabel(p) {
|
|
7086
|
-
const parts = [p.charName || p.citizenId];
|
|
7087
|
-
if (p.online) {
|
|
7088
|
-
if (p.name) parts.push(p.name);
|
|
7089
|
-
if (p.id != null) parts.push(`#${p.id}`);
|
|
7090
|
-
}
|
|
7091
|
-
return parts.join(" \xB7 ");
|
|
7092
|
-
}
|
|
7093
7344
|
function usePickDoor() {
|
|
7094
7345
|
const begin = useAdminToolStore((s) => s.begin);
|
|
7095
7346
|
return async () => {
|
|
@@ -7366,6 +7617,7 @@ function BlipMarker({
|
|
|
7366
7617
|
);
|
|
7367
7618
|
}
|
|
7368
7619
|
|
|
7620
|
+
exports.AccessOverrideSection = AccessOverrideSection;
|
|
7369
7621
|
exports.AccountSelect = AccountSelect;
|
|
7370
7622
|
exports.AdminPageTitle = AdminPageTitle;
|
|
7371
7623
|
exports.AnimPostFxSelect = AnimPostFxSelect;
|