dirk-cfx-react 1.1.87 → 1.1.90
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 +922 -57
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.cts +192 -2
- package/dist/components/index.d.ts +192 -2
- package/dist/components/index.js +913 -62
- package/dist/components/index.js.map +1 -1
- package/dist/hooks/index.cjs +159 -26
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.cts +16 -1
- package/dist/hooks/index.d.ts +16 -1
- package/dist/hooks/index.js +157 -28
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.cjs +1487 -474
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.js +1390 -397
- package/dist/index.js.map +1 -1
- package/dist/providers/index.cjs +162 -6
- package/dist/providers/index.cjs.map +1 -1
- package/dist/providers/index.d.cts +3 -1
- package/dist/providers/index.d.ts +3 -1
- package/dist/providers/index.js +163 -8
- package/dist/providers/index.js.map +1 -1
- package/dist/usePlayers-BlGBBevs.d.cts +37 -0
- package/dist/usePlayers-BlGBBevs.d.ts +37 -0
- package/dist/utils/index.cjs +45 -13
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +2 -1
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.js +45 -14
- package/dist/utils/index.js.map +1 -1
- package/package.json +123 -117
package/dist/index.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import { Flex, Text, Image as Image$1, createTheme, Box, Stack, Title as Title$1, Code, TextInput, Select, useMantineTheme, Tooltip,
|
|
1
|
+
import { Flex, Text, Image as Image$1, createTheme, alpha, Box, Stack, Title as Title$1, Code, TextInput, Select, useMantineTheme, Tooltip, Progress, RingProgress, Portal, Button, MantineProvider, NumberInput, MultiSelect, Loader, Switch, ActionIcon, ColorInput, Popover, BackgroundImage, Group, JsonInput } from '@mantine/core';
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
-
import
|
|
3
|
+
import React4, { createContext, memo, useRef, useEffect, useContext, useState, useCallback, useMemo, useLayoutEffect } from 'react';
|
|
4
4
|
import { create, useStore, createStore } from 'zustand';
|
|
5
5
|
import axios from 'axios';
|
|
6
6
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
7
7
|
import { motion, AnimatePresence, useMotionValue } from 'framer-motion';
|
|
8
|
-
import { Info, X, AlertTriangle, Trash2, RefreshCw, ChevronDown, Check, Copy, MapPin, Crosshair, EyeOff, Eye, RotateCcw, FlaskConical, ChevronUp, Palette, ArrowLeft, Undo2, Redo2, Save, History, XCircle, Code2, Search, Filter, User } from 'lucide-react';
|
|
8
|
+
import { Info, X, AlertTriangle, Trash2, RefreshCw, ChevronDown, Check, Copy, MapPin, Crosshair, EyeOff, Eye, RotateCcw, FlaskConical, ChevronUp, Palette, DoorOpen, Plus, Minus, ArrowLeft, Undo2, Redo2, Save, History, XCircle, Code2, Search, Filter, User } from 'lucide-react';
|
|
9
9
|
import clickSoundUrl from './click_sound-PNCRRTM4.mp3';
|
|
10
10
|
import hoverSoundUrl from './hover_sound-NBUA222C.mp3';
|
|
11
11
|
import { notifications } from '@mantine/notifications';
|
|
12
|
-
import { QueryClient, QueryClientProvider, useInfiniteQuery } from '@tanstack/react-query';
|
|
13
|
-
import { generateColors } from '@mantine/colors-generator';
|
|
12
|
+
import { QueryClient, QueryClientProvider, useQuery, keepPreviousData, useInfiniteQuery } from '@tanstack/react-query';
|
|
14
13
|
import '@mantine/core/styles.css';
|
|
15
14
|
import '@mantine/notifications/styles.css';
|
|
16
15
|
import './styles/fonts.css';
|
|
@@ -21,6 +20,12 @@ import { library } from '@fortawesome/fontawesome-svg-core';
|
|
|
21
20
|
import { fab } from '@fortawesome/free-brands-svg-icons';
|
|
22
21
|
import { far } from '@fortawesome/free-regular-svg-icons';
|
|
23
22
|
import { fas } from '@fortawesome/free-solid-svg-icons';
|
|
23
|
+
import { generateColors } from '@mantine/colors-generator';
|
|
24
|
+
import { createPortal } from 'react-dom';
|
|
25
|
+
import { CRS, tileLayer, latLngBounds, latLng } from 'leaflet';
|
|
26
|
+
import 'leaflet/dist/leaflet.css';
|
|
27
|
+
import { MapContainer, useMap } from 'react-leaflet';
|
|
28
|
+
import { Marker } from '@adamscybot/react-leaflet-component-marker';
|
|
24
29
|
import { z } from 'zod';
|
|
25
30
|
|
|
26
31
|
var __defProp = Object.defineProperty;
|
|
@@ -967,6 +972,18 @@ var BLIP_COLOR_DATA = BLIP_COLORS.map(([id, label2]) => ({
|
|
|
967
972
|
}));
|
|
968
973
|
var blipEntryMap = new Map(BLIP_ENTRIES.map(([id, name, ext]) => [String(id), { id, name, ext }]));
|
|
969
974
|
var blipColorMap = new Map(BLIP_COLORS.map(([id, label2, hex]) => [String(id), { id, label: label2, hex }]));
|
|
975
|
+
function getBlipEntry(spriteId) {
|
|
976
|
+
if (spriteId == null) return void 0;
|
|
977
|
+
return blipEntryMap.get(String(spriteId));
|
|
978
|
+
}
|
|
979
|
+
function getBlipColor(colorId) {
|
|
980
|
+
if (colorId == null) return void 0;
|
|
981
|
+
return blipColorMap.get(String(colorId));
|
|
982
|
+
}
|
|
983
|
+
function blipUrlForSprite(spriteId) {
|
|
984
|
+
const entry = getBlipEntry(spriteId);
|
|
985
|
+
return entry ? blipUrl(entry.name, entry.ext) : null;
|
|
986
|
+
}
|
|
970
987
|
var renderBlipOption = ({ option }) => {
|
|
971
988
|
const entry = blipEntryMap.get(option.value);
|
|
972
989
|
if (!entry) return option.label;
|
|
@@ -1244,11 +1261,11 @@ var colorNames = {
|
|
|
1244
1261
|
Yellow: { r: 255, g: 255, b: 0 },
|
|
1245
1262
|
YellowGreen: { r: 154, g: 205, b: 50 }
|
|
1246
1263
|
};
|
|
1247
|
-
function colorWithAlpha(color,
|
|
1264
|
+
function colorWithAlpha(color, alpha18) {
|
|
1248
1265
|
const lowerCasedColor = color.toLowerCase();
|
|
1249
1266
|
if (colorNames[lowerCasedColor]) {
|
|
1250
1267
|
const rgb = colorNames[lowerCasedColor];
|
|
1251
|
-
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${
|
|
1268
|
+
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha18})`;
|
|
1252
1269
|
}
|
|
1253
1270
|
if (/^#([A-Fa-f0-9]{6})$/.test(color)) {
|
|
1254
1271
|
const hex = color.slice(1);
|
|
@@ -1256,12 +1273,12 @@ function colorWithAlpha(color, alpha12) {
|
|
|
1256
1273
|
const r = bigint >> 16 & 255;
|
|
1257
1274
|
const g = bigint >> 8 & 255;
|
|
1258
1275
|
const b = bigint & 255;
|
|
1259
|
-
return `rgba(${r}, ${g}, ${b}, ${
|
|
1276
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha18})`;
|
|
1260
1277
|
}
|
|
1261
1278
|
if (/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/.test(color)) {
|
|
1262
1279
|
const result = color.match(/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/);
|
|
1263
1280
|
if (result) {
|
|
1264
|
-
return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${
|
|
1281
|
+
return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${alpha18})`;
|
|
1265
1282
|
}
|
|
1266
1283
|
}
|
|
1267
1284
|
return color;
|
|
@@ -1397,11 +1414,35 @@ function reportMissingLocale(key) {
|
|
|
1397
1414
|
fetchNui("REPORT_MISSING_LOCALE", { key }).catch(() => {
|
|
1398
1415
|
});
|
|
1399
1416
|
}
|
|
1417
|
+
var PACKAGE_DEFAULTS = {
|
|
1418
|
+
"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.",
|
|
1419
|
+
"cfgpanel_discard": "Discard",
|
|
1420
|
+
"cfgpanel_manual_edit": "Manual Edit",
|
|
1421
|
+
"cfgpanel_reset_defaults": "Reset Defaults",
|
|
1422
|
+
"cfgpanel_version": "Version",
|
|
1423
|
+
"cfgpanel_back_title": "Back to script list",
|
|
1424
|
+
"cfgpanel_undo": "Undo",
|
|
1425
|
+
"cfgpanel_redo": "Redo",
|
|
1426
|
+
"cfgpanel_save": "Save",
|
|
1427
|
+
"cfgpanel_saving": "Saving...",
|
|
1428
|
+
"cfgpanel_history": "History",
|
|
1429
|
+
"cfgpanel_reset_title": "Reset to Defaults",
|
|
1430
|
+
"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.",
|
|
1431
|
+
"cfgpanel_reset_confirm": "Reset Config",
|
|
1432
|
+
"cfgpanel_discard_title": "Discard Unsaved Changes?",
|
|
1433
|
+
"cfgpanel_discard_desc_back": "You have unsaved changes. Going back now will discard them.",
|
|
1434
|
+
"cfgpanel_discard_desc_close": "You have unsaved changes. Closing now will discard them.",
|
|
1435
|
+
"cfgpanel_discard_confirm_back": "Go Back Without Saving",
|
|
1436
|
+
"cfgpanel_discard_confirm_close": "Close Without Saving",
|
|
1437
|
+
"cfgpanel_json_title": "Config JSON",
|
|
1438
|
+
"cfgpanel_cancel": "Cancel",
|
|
1439
|
+
"cfgpanel_apply": "Apply",
|
|
1440
|
+
"cfgpanel_history_title": "Config History",
|
|
1441
|
+
"cfgpanel_close": "Close"
|
|
1442
|
+
};
|
|
1400
1443
|
var localeStore = create((set, get) => {
|
|
1401
1444
|
return {
|
|
1402
|
-
locales: {
|
|
1403
|
-
"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."
|
|
1404
|
-
},
|
|
1445
|
+
locales: { ...PACKAGE_DEFAULTS },
|
|
1405
1446
|
locale: (key, ...args) => {
|
|
1406
1447
|
const exists = get().locales[key];
|
|
1407
1448
|
if (!exists) reportMissingLocale(key);
|
|
@@ -1415,7 +1456,7 @@ var localeStore = create((set, get) => {
|
|
|
1415
1456
|
});
|
|
1416
1457
|
var locale = localeStore.getState().locale;
|
|
1417
1458
|
registerInitialFetch("GET_LOCALES", void 0).then((data) => {
|
|
1418
|
-
localeStore.setState({ locales: data });
|
|
1459
|
+
localeStore.setState({ locales: { ...PACKAGE_DEFAULTS, ...data } });
|
|
1419
1460
|
}).catch(() => {
|
|
1420
1461
|
});
|
|
1421
1462
|
if (typeof window !== "undefined") {
|
|
@@ -1423,7 +1464,8 @@ if (typeof window !== "undefined") {
|
|
|
1423
1464
|
const msg = event.data;
|
|
1424
1465
|
if (!msg || msg.action !== "UPDATE_DIRK_LIB_LOCALES") return;
|
|
1425
1466
|
if (!msg.data || typeof msg.data !== "object") return;
|
|
1426
|
-
|
|
1467
|
+
if (Object.keys(msg.data).length === 0) return;
|
|
1468
|
+
localeStore.setState({ locales: { ...PACKAGE_DEFAULTS, ...msg.data } });
|
|
1427
1469
|
});
|
|
1428
1470
|
}
|
|
1429
1471
|
|
|
@@ -1949,15 +1991,21 @@ var useFrameworkGroups = create(() => ({
|
|
|
1949
1991
|
gangs: [],
|
|
1950
1992
|
loaded: false
|
|
1951
1993
|
}));
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1994
|
+
var frameworkGroupsRequested = false;
|
|
1995
|
+
function ensureFrameworkGroups() {
|
|
1996
|
+
if (frameworkGroupsRequested) return;
|
|
1997
|
+
frameworkGroupsRequested = true;
|
|
1998
|
+
fetchNui("GET_FRAMEWORK_GROUPS", void 0).then((data) => {
|
|
1999
|
+
useFrameworkGroups.setState({
|
|
2000
|
+
jobs: Array.isArray(data?.jobs) ? data.jobs : [],
|
|
2001
|
+
gangs: Array.isArray(data?.gangs) ? data.gangs : [],
|
|
2002
|
+
loaded: true
|
|
2003
|
+
});
|
|
2004
|
+
}).catch(() => {
|
|
2005
|
+
frameworkGroupsRequested = false;
|
|
2006
|
+
useFrameworkGroups.setState({ loaded: true });
|
|
1957
2007
|
});
|
|
1958
|
-
}
|
|
1959
|
-
useFrameworkGroups.setState({ loaded: true });
|
|
1960
|
-
});
|
|
2008
|
+
}
|
|
1961
2009
|
function selectAllGroups(state) {
|
|
1962
2010
|
return [...state.jobs, ...state.gangs];
|
|
1963
2011
|
}
|
|
@@ -2991,7 +3039,7 @@ function NavigationProvider({ children, defaultPage }) {
|
|
|
2991
3039
|
}
|
|
2992
3040
|
function NavBar(props) {
|
|
2993
3041
|
const pageId = useNavigation((state) => state.pageId);
|
|
2994
|
-
const
|
|
3042
|
+
const store2 = useNavigationStore();
|
|
2995
3043
|
return /* @__PURE__ */ jsx(
|
|
2996
3044
|
SegmentedControl,
|
|
2997
3045
|
{
|
|
@@ -3000,7 +3048,7 @@ function NavBar(props) {
|
|
|
3000
3048
|
value: pageId,
|
|
3001
3049
|
items: props.items,
|
|
3002
3050
|
onChange: (value) => {
|
|
3003
|
-
|
|
3051
|
+
store2.setState({ pageId: value });
|
|
3004
3052
|
}
|
|
3005
3053
|
}
|
|
3006
3054
|
);
|
|
@@ -4307,29 +4355,29 @@ function FormProvider({
|
|
|
4307
4355
|
return /* @__PURE__ */ jsx(FormContext.Provider, { value: storeRef.current, children });
|
|
4308
4356
|
}
|
|
4309
4357
|
function useForm() {
|
|
4310
|
-
const
|
|
4311
|
-
if (!
|
|
4358
|
+
const store2 = useContext(FormContext);
|
|
4359
|
+
if (!store2) {
|
|
4312
4360
|
throw new Error("useForm must be used inside <FormProvider>");
|
|
4313
4361
|
}
|
|
4314
|
-
const state = useStore(
|
|
4362
|
+
const state = useStore(store2);
|
|
4315
4363
|
const changedFields = useMemo(() => {
|
|
4316
4364
|
return collectChangedPaths(state.values, state.initialValues);
|
|
4317
4365
|
}, [state.values, state.initialValues]);
|
|
4318
4366
|
return { ...state, changedFields, changedCount: changedFields.length };
|
|
4319
4367
|
}
|
|
4320
4368
|
function useFormField(path) {
|
|
4321
|
-
const
|
|
4322
|
-
if (!
|
|
4369
|
+
const store2 = useContext(FormContext);
|
|
4370
|
+
if (!store2) {
|
|
4323
4371
|
throw new Error("useFormField must be used inside <FormProvider>");
|
|
4324
4372
|
}
|
|
4325
|
-
return useStore(
|
|
4373
|
+
return useStore(store2, (s) => getNested(s.values, path));
|
|
4326
4374
|
}
|
|
4327
4375
|
function useFormFields(...paths) {
|
|
4328
|
-
const
|
|
4329
|
-
if (!
|
|
4376
|
+
const store2 = useContext(FormContext);
|
|
4377
|
+
if (!store2) {
|
|
4330
4378
|
throw new Error("useFormFields must be used inside <FormProvider>");
|
|
4331
4379
|
}
|
|
4332
|
-
return useStore(
|
|
4380
|
+
return useStore(store2, (s) => {
|
|
4333
4381
|
const result = {};
|
|
4334
4382
|
for (const path of paths) {
|
|
4335
4383
|
result[path] = getNested(s.values, path);
|
|
@@ -4338,18 +4386,18 @@ function useFormFields(...paths) {
|
|
|
4338
4386
|
});
|
|
4339
4387
|
}
|
|
4340
4388
|
function useFormError(path) {
|
|
4341
|
-
const
|
|
4342
|
-
if (!
|
|
4389
|
+
const store2 = useContext(FormContext);
|
|
4390
|
+
if (!store2) {
|
|
4343
4391
|
throw new Error("useFormError must be used inside <FormProvider>");
|
|
4344
4392
|
}
|
|
4345
|
-
return useStore(
|
|
4393
|
+
return useStore(store2, (s) => s.errors[path]);
|
|
4346
4394
|
}
|
|
4347
4395
|
function useFormErrors(...paths) {
|
|
4348
|
-
const
|
|
4349
|
-
if (!
|
|
4396
|
+
const store2 = useContext(FormContext);
|
|
4397
|
+
if (!store2) {
|
|
4350
4398
|
throw new Error("useFormErrors must be used inside <FormProvider>");
|
|
4351
4399
|
}
|
|
4352
|
-
return useStore(
|
|
4400
|
+
return useStore(store2, (s) => {
|
|
4353
4401
|
const result = {};
|
|
4354
4402
|
for (const path of paths) {
|
|
4355
4403
|
result[path] = s.errors[path];
|
|
@@ -4358,12 +4406,223 @@ function useFormErrors(...paths) {
|
|
|
4358
4406
|
});
|
|
4359
4407
|
}
|
|
4360
4408
|
function useFormActions() {
|
|
4361
|
-
const
|
|
4362
|
-
if (!
|
|
4409
|
+
const store2 = useContext(FormContext);
|
|
4410
|
+
if (!store2) {
|
|
4363
4411
|
throw new Error("useFormActions must be used inside <FormProvider>");
|
|
4364
4412
|
}
|
|
4365
|
-
return
|
|
4413
|
+
return store2.getState();
|
|
4414
|
+
}
|
|
4415
|
+
var store = /* @__PURE__ */ new Map();
|
|
4416
|
+
var listeners = /* @__PURE__ */ new Map();
|
|
4417
|
+
function notify(key) {
|
|
4418
|
+
const ls = listeners.get(key);
|
|
4419
|
+
if (!ls) return;
|
|
4420
|
+
ls.forEach((fn) => fn());
|
|
4421
|
+
}
|
|
4422
|
+
function useAdminState(key, initial) {
|
|
4423
|
+
const [, setTick] = useState(0);
|
|
4424
|
+
useEffect(() => {
|
|
4425
|
+
const set = listeners.get(key) ?? /* @__PURE__ */ new Set();
|
|
4426
|
+
listeners.set(key, set);
|
|
4427
|
+
const handler = () => setTick((t3) => t3 + 1);
|
|
4428
|
+
set.add(handler);
|
|
4429
|
+
return () => {
|
|
4430
|
+
set.delete(handler);
|
|
4431
|
+
if (set.size === 0) listeners.delete(key);
|
|
4432
|
+
};
|
|
4433
|
+
}, [key]);
|
|
4434
|
+
const value = store.has(key) ? store.get(key) : initial;
|
|
4435
|
+
const setValue = (v) => {
|
|
4436
|
+
const next = typeof v === "function" ? v(value) : v;
|
|
4437
|
+
store.set(key, next);
|
|
4438
|
+
notify(key);
|
|
4439
|
+
};
|
|
4440
|
+
return [value, setValue];
|
|
4441
|
+
}
|
|
4442
|
+
function clearAdminState(key) {
|
|
4443
|
+
if (key) {
|
|
4444
|
+
store.delete(key);
|
|
4445
|
+
notify(key);
|
|
4446
|
+
} else {
|
|
4447
|
+
const keys = Array.from(store.keys());
|
|
4448
|
+
store.clear();
|
|
4449
|
+
keys.forEach(notify);
|
|
4450
|
+
}
|
|
4366
4451
|
}
|
|
4452
|
+
var label = {
|
|
4453
|
+
fontSize: "var(--mantine-font-size-xs)",
|
|
4454
|
+
fontFamily: "Akrobat Bold",
|
|
4455
|
+
letterSpacing: "0.05em",
|
|
4456
|
+
textTransform: "uppercase"
|
|
4457
|
+
};
|
|
4458
|
+
var error = {
|
|
4459
|
+
fontSize: "var(--mantine-font-size-xs)",
|
|
4460
|
+
fontFamily: "Akrobat Regular"
|
|
4461
|
+
};
|
|
4462
|
+
var description = {
|
|
4463
|
+
fontSize: "var(--mantine-font-size-xs)"
|
|
4464
|
+
};
|
|
4465
|
+
var genericInputStyles = {
|
|
4466
|
+
styles: {
|
|
4467
|
+
label,
|
|
4468
|
+
error,
|
|
4469
|
+
description,
|
|
4470
|
+
input: {
|
|
4471
|
+
background: "rgba(255,255,255,0.04)",
|
|
4472
|
+
border: "0.1vh solid rgba(255,255,255,0.08)",
|
|
4473
|
+
color: "rgba(255,255,255,0.85)",
|
|
4474
|
+
minHeight: "4vh"
|
|
4475
|
+
}
|
|
4476
|
+
}
|
|
4477
|
+
};
|
|
4478
|
+
var theme = createTheme({
|
|
4479
|
+
primaryColor: "dirk",
|
|
4480
|
+
primaryShade: 9,
|
|
4481
|
+
defaultRadius: "xs",
|
|
4482
|
+
fontFamily: "Akrobat Regular, sans-serif",
|
|
4483
|
+
radius: {
|
|
4484
|
+
xxs: "0.3vh",
|
|
4485
|
+
xs: "0.5vh",
|
|
4486
|
+
sm: "0.75vh",
|
|
4487
|
+
md: "1vh",
|
|
4488
|
+
lg: "1.5vh",
|
|
4489
|
+
xl: "2vh",
|
|
4490
|
+
xxl: "3vh"
|
|
4491
|
+
},
|
|
4492
|
+
fontSizes: {
|
|
4493
|
+
xxs: "1.2vh",
|
|
4494
|
+
xs: "1.5vh",
|
|
4495
|
+
sm: "1.8vh",
|
|
4496
|
+
md: "2.2vh",
|
|
4497
|
+
lg: "2.8vh",
|
|
4498
|
+
xl: "3.3vh",
|
|
4499
|
+
xxl: "3.8vh"
|
|
4500
|
+
},
|
|
4501
|
+
lineHeights: {
|
|
4502
|
+
xxs: "1.4vh",
|
|
4503
|
+
xs: "1.8vh",
|
|
4504
|
+
sm: "2.2vh",
|
|
4505
|
+
md: "2.8vh",
|
|
4506
|
+
lg: "3.3vh",
|
|
4507
|
+
xl: "3.8vh"
|
|
4508
|
+
},
|
|
4509
|
+
spacing: {
|
|
4510
|
+
xxs: "0.5vh",
|
|
4511
|
+
xs: "0.75vh",
|
|
4512
|
+
sm: "1.5vh",
|
|
4513
|
+
md: "2vh",
|
|
4514
|
+
lg: "3vh",
|
|
4515
|
+
xl: "4vh",
|
|
4516
|
+
xxl: "5vh"
|
|
4517
|
+
},
|
|
4518
|
+
components: {
|
|
4519
|
+
Progress: {
|
|
4520
|
+
styles: {
|
|
4521
|
+
label: {
|
|
4522
|
+
fontFamily: "Akrobat Bold",
|
|
4523
|
+
letterSpacing: "0.05em",
|
|
4524
|
+
textTransform: "uppercase"
|
|
4525
|
+
},
|
|
4526
|
+
root: {
|
|
4527
|
+
backgroundColor: "rgba(77, 77, 77, 0.4)"
|
|
4528
|
+
}
|
|
4529
|
+
}
|
|
4530
|
+
},
|
|
4531
|
+
Input: genericInputStyles,
|
|
4532
|
+
TextInput: genericInputStyles,
|
|
4533
|
+
NumberInput: genericInputStyles,
|
|
4534
|
+
Select: genericInputStyles,
|
|
4535
|
+
MultiSelect: genericInputStyles,
|
|
4536
|
+
Textarea: genericInputStyles,
|
|
4537
|
+
ColorInput: genericInputStyles,
|
|
4538
|
+
DateInput: genericInputStyles,
|
|
4539
|
+
// Mantine's <Button> defaults to rem-based heights (xs ≈ 1.875rem)
|
|
4540
|
+
// which doesn't match this theme's vh-based input min-heights, so
|
|
4541
|
+
// `<Button size="xs">` rendered next to `<TextInput size="xs">` ends
|
|
4542
|
+
// up visibly shorter. Pin the button heights to the same vh values
|
|
4543
|
+
// the inputs use so xs-everything lines up out of the box.
|
|
4544
|
+
Button: {
|
|
4545
|
+
styles: {
|
|
4546
|
+
label: {
|
|
4547
|
+
fontFamily: "Akrobat Bold",
|
|
4548
|
+
letterSpacing: "0.05em",
|
|
4549
|
+
textTransform: "uppercase"
|
|
4550
|
+
},
|
|
4551
|
+
root: {
|
|
4552
|
+
// Mantine maps these to --button-height per size; setting them
|
|
4553
|
+
// directly here keeps native Button sizing logic intact.
|
|
4554
|
+
}
|
|
4555
|
+
},
|
|
4556
|
+
vars: (_theme, props) => {
|
|
4557
|
+
const heights = {
|
|
4558
|
+
xs: "4vh",
|
|
4559
|
+
sm: "4.5vh",
|
|
4560
|
+
md: "5vh",
|
|
4561
|
+
lg: "5.5vh",
|
|
4562
|
+
xl: "6vh"
|
|
4563
|
+
};
|
|
4564
|
+
const h = heights[props.size ?? "sm"] ?? "4.5vh";
|
|
4565
|
+
return {
|
|
4566
|
+
root: {
|
|
4567
|
+
"--button-height": h
|
|
4568
|
+
}
|
|
4569
|
+
};
|
|
4570
|
+
}
|
|
4571
|
+
},
|
|
4572
|
+
Pill: {
|
|
4573
|
+
styles: (theme2) => ({
|
|
4574
|
+
root: {
|
|
4575
|
+
display: "inline-flex",
|
|
4576
|
+
alignItems: "center",
|
|
4577
|
+
justifyContent: "space-between",
|
|
4578
|
+
backgroundColor: "rgba(76, 76, 76, 0.3)",
|
|
4579
|
+
height: "fit-content",
|
|
4580
|
+
textTransform: "uppercase",
|
|
4581
|
+
letterSpacing: "0.05em",
|
|
4582
|
+
fontFamily: "Akrobat Bold",
|
|
4583
|
+
fontSize: "1.25vh",
|
|
4584
|
+
borderRadius: theme2.defaultRadius,
|
|
4585
|
+
paddingBottom: "0.5vh",
|
|
4586
|
+
paddingTop: "0.5vh"
|
|
4587
|
+
}
|
|
4588
|
+
})
|
|
4589
|
+
},
|
|
4590
|
+
// Mantine's <Tooltip> defaults to a white card with black text — looks
|
|
4591
|
+
// jarring against every dirk consumer's dark configurator. Every script
|
|
4592
|
+
// used to hand-paste this dark style block per Tooltip; centralised here
|
|
4593
|
+
// so consumers get the right look automatically and never need to think
|
|
4594
|
+
// about it again.
|
|
4595
|
+
Tooltip: {
|
|
4596
|
+
styles: (theme2) => ({
|
|
4597
|
+
tooltip: {
|
|
4598
|
+
background: alpha(theme2.colors.dark[7], 0.95),
|
|
4599
|
+
border: "0.1vh solid rgba(255,255,255,0.1)",
|
|
4600
|
+
color: "rgba(255,255,255,0.75)",
|
|
4601
|
+
fontFamily: "Akrobat Bold",
|
|
4602
|
+
fontSize: "1.3vh",
|
|
4603
|
+
lineHeight: 1.3,
|
|
4604
|
+
padding: "0.6vh 0.8vh",
|
|
4605
|
+
letterSpacing: "0.03em"
|
|
4606
|
+
}
|
|
4607
|
+
})
|
|
4608
|
+
}
|
|
4609
|
+
},
|
|
4610
|
+
colors: {
|
|
4611
|
+
dirk: [
|
|
4612
|
+
"#ffffff",
|
|
4613
|
+
"#f3fce9",
|
|
4614
|
+
"#dbf5bd",
|
|
4615
|
+
"#c3ee91",
|
|
4616
|
+
"#ace765",
|
|
4617
|
+
"#94e039",
|
|
4618
|
+
"#7ac61f",
|
|
4619
|
+
"#5f9a18",
|
|
4620
|
+
"#29420a",
|
|
4621
|
+
"#446e11"
|
|
4622
|
+
]
|
|
4623
|
+
}
|
|
4624
|
+
});
|
|
4625
|
+
var theme_default = theme;
|
|
4367
4626
|
var useNuiEvent = (action, handler) => {
|
|
4368
4627
|
const savedHandler = useRef(noop);
|
|
4369
4628
|
useEffect(() => {
|
|
@@ -4382,13 +4641,35 @@ var useNuiEvent = (action, handler) => {
|
|
|
4382
4641
|
return () => window.removeEventListener("message", eventListener);
|
|
4383
4642
|
}, [action]);
|
|
4384
4643
|
};
|
|
4644
|
+
|
|
4645
|
+
// src/utils/mergeMantineTheme.ts
|
|
4646
|
+
var isValidColorScale = (v) => Array.isArray(v) && v.length === 10 && v.every((shade) => typeof shade === "string");
|
|
4647
|
+
function mergeMantineThemeSafe(base, custom, override) {
|
|
4648
|
+
const colors = { ...base.colors };
|
|
4649
|
+
if (custom && isValidColorScale(custom)) {
|
|
4650
|
+
colors["custom"] = custom;
|
|
4651
|
+
} else if (!colors["custom"]) {
|
|
4652
|
+
const fallback = base.colors && base.colors.dirk;
|
|
4653
|
+
if (fallback && isValidColorScale(fallback)) {
|
|
4654
|
+
colors["custom"] = fallback;
|
|
4655
|
+
}
|
|
4656
|
+
}
|
|
4657
|
+
return {
|
|
4658
|
+
...base,
|
|
4659
|
+
...override,
|
|
4660
|
+
colors: {
|
|
4661
|
+
...colors,
|
|
4662
|
+
...override?.colors ?? {}
|
|
4663
|
+
}
|
|
4664
|
+
};
|
|
4665
|
+
}
|
|
4385
4666
|
var _instance = null;
|
|
4386
4667
|
function getScriptConfigInstance() {
|
|
4387
4668
|
if (!_instance) throw new Error("[dirk-cfx-react] createScriptConfig must be called before using ConfigPanel");
|
|
4388
4669
|
return _instance;
|
|
4389
4670
|
}
|
|
4390
4671
|
function createScriptConfig(defaultValue) {
|
|
4391
|
-
const
|
|
4672
|
+
const store2 = create(() => defaultValue);
|
|
4392
4673
|
let clientVersion = 0;
|
|
4393
4674
|
const useScriptConfigHooks = () => {
|
|
4394
4675
|
useNuiEvent("UPDATE_SCRIPT_CONFIG", (data) => {
|
|
@@ -4397,7 +4678,7 @@ function createScriptConfig(defaultValue) {
|
|
|
4397
4678
|
clientVersion = data.clientVersion;
|
|
4398
4679
|
}
|
|
4399
4680
|
if (data.config && typeof data.config === "object") {
|
|
4400
|
-
|
|
4681
|
+
store2.setState((prev) => ({ ...prev, ...data.config }));
|
|
4401
4682
|
}
|
|
4402
4683
|
});
|
|
4403
4684
|
};
|
|
@@ -4405,7 +4686,7 @@ function createScriptConfig(defaultValue) {
|
|
|
4405
4686
|
try {
|
|
4406
4687
|
const response = await fetchNui("GET_FULL_SCRIPT_CONFIG");
|
|
4407
4688
|
if (response?.success && response.data?.config) {
|
|
4408
|
-
|
|
4689
|
+
store2.setState(() => response.data.config);
|
|
4409
4690
|
if (typeof response.data.clientVersion === "number") {
|
|
4410
4691
|
clientVersion = response.data.clientVersion;
|
|
4411
4692
|
}
|
|
@@ -4416,7 +4697,7 @@ function createScriptConfig(defaultValue) {
|
|
|
4416
4697
|
return null;
|
|
4417
4698
|
};
|
|
4418
4699
|
const updateScriptConfig = async (newConfig) => {
|
|
4419
|
-
|
|
4700
|
+
store2.setState((prev) => ({ ...prev, ...newConfig }));
|
|
4420
4701
|
const response = await fetchNui("UPDATE_SCRIPT_CONFIG", {
|
|
4421
4702
|
data: newConfig,
|
|
4422
4703
|
expectedVersion: clientVersion
|
|
@@ -4425,7 +4706,7 @@ function createScriptConfig(defaultValue) {
|
|
|
4425
4706
|
clientVersion = response.meta.client_version;
|
|
4426
4707
|
}
|
|
4427
4708
|
if (response?.success === false && response?.meta?.latestData) {
|
|
4428
|
-
|
|
4709
|
+
store2.setState((prev) => ({ ...prev, ...response.meta.latestData }));
|
|
4429
4710
|
}
|
|
4430
4711
|
return response;
|
|
4431
4712
|
};
|
|
@@ -4437,25 +4718,248 @@ function createScriptConfig(defaultValue) {
|
|
|
4437
4718
|
if (response?.success) {
|
|
4438
4719
|
const fresh = await fetchScriptConfig();
|
|
4439
4720
|
if (fresh) {
|
|
4440
|
-
|
|
4721
|
+
store2.setState(() => fresh);
|
|
4441
4722
|
}
|
|
4442
4723
|
}
|
|
4443
4724
|
return response;
|
|
4444
4725
|
};
|
|
4445
4726
|
_instance = {
|
|
4446
|
-
store,
|
|
4727
|
+
store: store2,
|
|
4447
4728
|
updateConfig: updateScriptConfig,
|
|
4448
4729
|
resetConfig,
|
|
4449
4730
|
getHistory: getScriptConfigHistory,
|
|
4450
4731
|
fetchConfig: fetchScriptConfig
|
|
4451
4732
|
};
|
|
4452
|
-
return { store, updateScriptConfig, resetConfig, getScriptConfigHistory, useScriptConfigHooks, fetchScriptConfig };
|
|
4733
|
+
return { store: store2, updateScriptConfig, resetConfig, getScriptConfigHistory, useScriptConfigHooks, fetchScriptConfig };
|
|
4734
|
+
}
|
|
4735
|
+
var DirkErrorBoundary = class extends React4.Component {
|
|
4736
|
+
constructor() {
|
|
4737
|
+
super(...arguments);
|
|
4738
|
+
__publicField(this, "state", { error: null, stack: void 0 });
|
|
4739
|
+
}
|
|
4740
|
+
static getDerivedStateFromError(error2) {
|
|
4741
|
+
return { error: error2 };
|
|
4742
|
+
}
|
|
4743
|
+
componentDidCatch(error2, info) {
|
|
4744
|
+
console.group("\u{1F525} Dirk UI Crash");
|
|
4745
|
+
console.error("Error:", error2);
|
|
4746
|
+
console.error("Component Stack:", info.componentStack);
|
|
4747
|
+
console.groupEnd();
|
|
4748
|
+
}
|
|
4749
|
+
render() {
|
|
4750
|
+
if (!this.state.error) return this.props.children;
|
|
4751
|
+
return /* @__PURE__ */ jsx(
|
|
4752
|
+
Box,
|
|
4753
|
+
{
|
|
4754
|
+
style: {
|
|
4755
|
+
position: "fixed",
|
|
4756
|
+
inset: 0,
|
|
4757
|
+
width: "100vw",
|
|
4758
|
+
height: "100vh",
|
|
4759
|
+
background: "rgba(10, 10, 12, 0.92)",
|
|
4760
|
+
display: "flex",
|
|
4761
|
+
alignItems: "center",
|
|
4762
|
+
justifyContent: "center",
|
|
4763
|
+
padding: "2rem",
|
|
4764
|
+
zIndex: 999999
|
|
4765
|
+
},
|
|
4766
|
+
children: /* @__PURE__ */ jsx(
|
|
4767
|
+
Box,
|
|
4768
|
+
{
|
|
4769
|
+
maw: 900,
|
|
4770
|
+
w: "100%",
|
|
4771
|
+
p: "lg",
|
|
4772
|
+
style: {
|
|
4773
|
+
background: "rgba(20,20,24,0.75)",
|
|
4774
|
+
border: "1px solid rgba(255,255,255,0.08)",
|
|
4775
|
+
borderRadius: "10px",
|
|
4776
|
+
boxShadow: "0 10px 40px rgba(0,0,0,0.6)"
|
|
4777
|
+
},
|
|
4778
|
+
children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
4779
|
+
/* @__PURE__ */ jsx(Title$1, { order: 2, c: "red.5", children: "Dirk UI Crash" }),
|
|
4780
|
+
/* @__PURE__ */ jsx(Text, { c: "dimmed", size: "sm", children: "The interface encountered a fatal error and stopped rendering." }),
|
|
4781
|
+
/* @__PURE__ */ jsx(Code, { block: true, style: { maxHeight: 150, overflow: "auto" }, children: this.state.error?.message }),
|
|
4782
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Check console for full stack trace" })
|
|
4783
|
+
] })
|
|
4784
|
+
}
|
|
4785
|
+
)
|
|
4786
|
+
}
|
|
4787
|
+
);
|
|
4788
|
+
}
|
|
4789
|
+
};
|
|
4790
|
+
var useAdminToolStore = create((set, get) => ({
|
|
4791
|
+
active: null,
|
|
4792
|
+
begin: (spec) => new Promise((resolve) => {
|
|
4793
|
+
const prev = get().active;
|
|
4794
|
+
if (prev) prev.resolve(null);
|
|
4795
|
+
set({ active: { ...spec, resolve } });
|
|
4796
|
+
}),
|
|
4797
|
+
resolveActive: (value) => {
|
|
4798
|
+
const cur = get().active;
|
|
4799
|
+
if (!cur) return;
|
|
4800
|
+
cur.resolve(value);
|
|
4801
|
+
set({ active: null });
|
|
4802
|
+
},
|
|
4803
|
+
cancelActive: () => {
|
|
4804
|
+
const cur = get().active;
|
|
4805
|
+
if (!cur) return;
|
|
4806
|
+
cur.resolve(null);
|
|
4807
|
+
set({ active: null });
|
|
4808
|
+
}
|
|
4809
|
+
}));
|
|
4810
|
+
|
|
4811
|
+
// src/components/AdminTools/AdminOverlays.tsx
|
|
4812
|
+
var listenerInstalled = false;
|
|
4813
|
+
function installNuiListener() {
|
|
4814
|
+
if (listenerInstalled || typeof window === "undefined") return;
|
|
4815
|
+
listenerInstalled = true;
|
|
4816
|
+
window.addEventListener("message", (e) => {
|
|
4817
|
+
const msg = e?.data;
|
|
4818
|
+
if (!msg || typeof msg !== "object" || typeof msg.action !== "string") return;
|
|
4819
|
+
const action = msg.action;
|
|
4820
|
+
const cur = useAdminToolStore.getState().active;
|
|
4821
|
+
if (!cur) return;
|
|
4822
|
+
if (action === `${cur.id}_RESULT`) {
|
|
4823
|
+
useAdminToolStore.getState().resolveActive(msg.data ?? null);
|
|
4824
|
+
} else if (action === `${cur.id}_CANCELLED`) {
|
|
4825
|
+
useAdminToolStore.getState().cancelActive();
|
|
4826
|
+
}
|
|
4827
|
+
});
|
|
4828
|
+
}
|
|
4829
|
+
var BODY_HIDE_STYLE_ID = "dirk-instruction-panel-style";
|
|
4830
|
+
var BODY_HIDE_ATTR = "data-dirk-instruction-active";
|
|
4831
|
+
var OVERLAY_ATTR = "data-dirk-instruction-overlay";
|
|
4832
|
+
function ensureBodyHideStyle() {
|
|
4833
|
+
if (typeof document === "undefined") return;
|
|
4834
|
+
if (document.getElementById(BODY_HIDE_STYLE_ID)) return;
|
|
4835
|
+
const el = document.createElement("style");
|
|
4836
|
+
el.id = BODY_HIDE_STYLE_ID;
|
|
4837
|
+
el.textContent = `
|
|
4838
|
+
body[${BODY_HIDE_ATTR}] > *:not([${OVERLAY_ATTR}]) {
|
|
4839
|
+
visibility: hidden !important;
|
|
4840
|
+
opacity: 0 !important;
|
|
4841
|
+
pointer-events: none !important;
|
|
4842
|
+
}
|
|
4843
|
+
`;
|
|
4844
|
+
document.head.appendChild(el);
|
|
4845
|
+
}
|
|
4846
|
+
function AdminOverlays() {
|
|
4847
|
+
const active = useAdminToolStore((s) => s.active);
|
|
4848
|
+
useEffect(() => {
|
|
4849
|
+
installNuiListener();
|
|
4850
|
+
}, []);
|
|
4851
|
+
useEffect(() => {
|
|
4852
|
+
if (!active || typeof document === "undefined") return;
|
|
4853
|
+
ensureBodyHideStyle();
|
|
4854
|
+
document.body.setAttribute(BODY_HIDE_ATTR, "");
|
|
4855
|
+
return () => {
|
|
4856
|
+
document.body.removeAttribute(BODY_HIDE_ATTR);
|
|
4857
|
+
};
|
|
4858
|
+
}, [active]);
|
|
4859
|
+
return null;
|
|
4453
4860
|
}
|
|
4454
|
-
|
|
4861
|
+
library.add(fas, far, fab);
|
|
4862
|
+
var dirkQueryClient = new QueryClient({
|
|
4455
4863
|
defaultOptions: { queries: { staleTime: 3e4, gcTime: 5 * 6e4 } }
|
|
4456
4864
|
});
|
|
4457
|
-
function
|
|
4458
|
-
|
|
4865
|
+
function DirkProvider({ children, overideResourceName, themeOverride }) {
|
|
4866
|
+
const {
|
|
4867
|
+
primaryColor,
|
|
4868
|
+
primaryShade,
|
|
4869
|
+
customTheme,
|
|
4870
|
+
game
|
|
4871
|
+
} = useSettings();
|
|
4872
|
+
localeStore((s) => s.locales);
|
|
4873
|
+
const [scTheme, setScTheme] = useState(null);
|
|
4874
|
+
useLayoutEffect(() => {
|
|
4875
|
+
useSettings.setState({
|
|
4876
|
+
overideResourceName
|
|
4877
|
+
});
|
|
4878
|
+
}, [overideResourceName]);
|
|
4879
|
+
useEffect(() => {
|
|
4880
|
+
fetchNui("NUI_READY").catch(() => {
|
|
4881
|
+
});
|
|
4882
|
+
Promise.all([
|
|
4883
|
+
fetchNui("GET_SETTINGS"),
|
|
4884
|
+
fetchNui("GET_RESOURCE_VERSION", void 0, { version: "dev" })
|
|
4885
|
+
]).then(([data, resourceInfo]) => {
|
|
4886
|
+
useSettings.setState({
|
|
4887
|
+
...data,
|
|
4888
|
+
resourceVersion: resourceInfo?.version || "dev"
|
|
4889
|
+
});
|
|
4890
|
+
}).catch((err) => {
|
|
4891
|
+
console.error("Failed to fetch initial settings within dirk-cfx-react:", err);
|
|
4892
|
+
});
|
|
4893
|
+
}, []);
|
|
4894
|
+
useNuiEvent("UPDATE_DIRK_LIB_SETTINGS", (data) => {
|
|
4895
|
+
if (!data || typeof data !== "object") return;
|
|
4896
|
+
useSettings.setState(data);
|
|
4897
|
+
});
|
|
4898
|
+
useNuiEvent(
|
|
4899
|
+
"UPDATE_SCRIPT_CONFIG",
|
|
4900
|
+
(data) => {
|
|
4901
|
+
if (!data || !data.config || typeof data.config !== "object") return;
|
|
4902
|
+
try {
|
|
4903
|
+
const inst = getScriptConfigInstance();
|
|
4904
|
+
inst.store.setState((prev) => ({ ...prev, ...data.config }));
|
|
4905
|
+
} catch {
|
|
4906
|
+
}
|
|
4907
|
+
}
|
|
4908
|
+
);
|
|
4909
|
+
useEffect(() => {
|
|
4910
|
+
let unsubscribe;
|
|
4911
|
+
try {
|
|
4912
|
+
const inst = getScriptConfigInstance();
|
|
4913
|
+
setScTheme(inst.store.getState()?.theme ?? null);
|
|
4914
|
+
const subscribable = inst.store;
|
|
4915
|
+
if (typeof subscribable.subscribe === "function") {
|
|
4916
|
+
unsubscribe = subscribable.subscribe((s) => {
|
|
4917
|
+
setScTheme(s?.theme ?? null);
|
|
4918
|
+
});
|
|
4919
|
+
}
|
|
4920
|
+
inst.fetchConfig?.().then((full) => {
|
|
4921
|
+
if (full && typeof full === "object") {
|
|
4922
|
+
setScTheme(full.theme ?? null);
|
|
4923
|
+
}
|
|
4924
|
+
}).catch(() => {
|
|
4925
|
+
});
|
|
4926
|
+
} catch {
|
|
4927
|
+
}
|
|
4928
|
+
return () => {
|
|
4929
|
+
unsubscribe?.();
|
|
4930
|
+
};
|
|
4931
|
+
}, []);
|
|
4932
|
+
const overrideActive = scTheme?.useOverride === true;
|
|
4933
|
+
const effectivePrimaryColor = overrideActive ? scTheme.primaryColor ?? primaryColor : primaryColor;
|
|
4934
|
+
const effectivePrimaryShade = overrideActive ? scTheme.primaryShade ?? primaryShade : primaryShade;
|
|
4935
|
+
const effectiveCustomTheme = overrideActive ? scTheme.customTheme ?? customTheme : customTheme;
|
|
4936
|
+
const mergedTheme = useMemo(
|
|
4937
|
+
() => mergeMantineThemeSafe(
|
|
4938
|
+
{ ...theme_default, primaryColor: effectivePrimaryColor, primaryShade: effectivePrimaryShade },
|
|
4939
|
+
effectiveCustomTheme,
|
|
4940
|
+
themeOverride
|
|
4941
|
+
),
|
|
4942
|
+
[effectivePrimaryColor, effectivePrimaryShade, effectiveCustomTheme, themeOverride]
|
|
4943
|
+
);
|
|
4944
|
+
useEffect(() => {
|
|
4945
|
+
document.body.style.fontFamily = game === "rdr3" ? '"Red Dead", sans-serif' : '"Akrobat Regular", sans-serif';
|
|
4946
|
+
}, [game]);
|
|
4947
|
+
const content = isEnvBrowser() ? /* @__PURE__ */ jsx(
|
|
4948
|
+
BackgroundImage,
|
|
4949
|
+
{
|
|
4950
|
+
w: "100vw",
|
|
4951
|
+
h: "100vh",
|
|
4952
|
+
src: game === "fivem" ? "https://i.ytimg.com/vi/TOxuNbXrO28/maxresdefault.jpg" : "https://raw.githubusercontent.com/Jump-On-Studios/RedM-jo_libs/refs/heads/main/source-repositories/Menu/public/assets/images/background_dev.jpg",
|
|
4953
|
+
children
|
|
4954
|
+
}
|
|
4955
|
+
) : children;
|
|
4956
|
+
return /* @__PURE__ */ jsx(QueryClientProvider, { client: dirkQueryClient, children: /* @__PURE__ */ jsx(MantineProvider, { theme: mergedTheme, defaultColorScheme: "dark", children: /* @__PURE__ */ jsxs(DirkErrorBoundary, { children: [
|
|
4957
|
+
content,
|
|
4958
|
+
/* @__PURE__ */ jsx(AdminOverlays, {})
|
|
4959
|
+
] }) }) });
|
|
4960
|
+
}
|
|
4961
|
+
function NavItemButton({
|
|
4962
|
+
icon: Icon,
|
|
4459
4963
|
label: label2,
|
|
4460
4964
|
active,
|
|
4461
4965
|
onClick
|
|
@@ -4532,7 +5036,7 @@ function ConfigJsonModal({
|
|
|
4532
5036
|
setError(e.message);
|
|
4533
5037
|
}
|
|
4534
5038
|
};
|
|
4535
|
-
return /* @__PURE__ */ jsxs(Modal, { title: "
|
|
5039
|
+
return /* @__PURE__ */ jsxs(Modal, { title: locale("cfgpanel_json_title"), icon: Code2, iconColor: color, onClose, width: "60vh", maxHeight: "80vh", zIndex: 200, children: [
|
|
4536
5040
|
/* @__PURE__ */ jsxs(Box, { flex: 1, p: "0.8vh", style: { overflowY: "auto" }, children: [
|
|
4537
5041
|
/* @__PURE__ */ jsx(
|
|
4538
5042
|
JsonInput,
|
|
@@ -4560,7 +5064,7 @@ function ConfigJsonModal({
|
|
|
4560
5064
|
style: { background: "transparent", border: `0.1vh solid ${theme2.colors.dark[6]}`, borderRadius: theme2.radius.xs, padding: `${theme2.spacing.xxs} ${theme2.spacing.xs}`, cursor: "pointer", display: "flex", alignItems: "center", gap: theme2.spacing.xxs },
|
|
4561
5065
|
children: [
|
|
4562
5066
|
/* @__PURE__ */ jsx(X, { color: "rgba(255,255,255,0.4)" }),
|
|
4563
|
-
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: "rgba(255,255,255,0.4)", children: "
|
|
5067
|
+
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: "rgba(255,255,255,0.4)", children: locale("cfgpanel_cancel") })
|
|
4564
5068
|
]
|
|
4565
5069
|
}
|
|
4566
5070
|
),
|
|
@@ -4573,7 +5077,7 @@ function ConfigJsonModal({
|
|
|
4573
5077
|
style: { background: alpha(color, 0.14), border: `0.1vh solid ${alpha(color, 0.4)}`, borderRadius: theme2.radius.xs, padding: `${theme2.spacing.xxs} ${theme2.spacing.xs}`, cursor: "pointer", display: "flex", alignItems: "center", gap: theme2.spacing.xxs },
|
|
4574
5078
|
children: [
|
|
4575
5079
|
/* @__PURE__ */ jsx(Check, { color }),
|
|
4576
|
-
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: color, children: "
|
|
5080
|
+
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: color, children: locale("cfgpanel_apply") })
|
|
4577
5081
|
]
|
|
4578
5082
|
}
|
|
4579
5083
|
)
|
|
@@ -4714,7 +5218,7 @@ function ConfigHistoryModal({
|
|
|
4714
5218
|
historyQuery.fetchNextPage();
|
|
4715
5219
|
}
|
|
4716
5220
|
};
|
|
4717
|
-
return /* @__PURE__ */ jsxs(Modal, { title: "
|
|
5221
|
+
return /* @__PURE__ */ jsxs(Modal, { title: locale("cfgpanel_history_title"), icon: History, iconColor: color, onClose, width: "88vh", maxHeight: "82vh", zIndex: 260, children: [
|
|
4718
5222
|
/* @__PURE__ */ jsxs(Flex, { direction: "column", style: { flex: 1, minHeight: 0 }, children: [
|
|
4719
5223
|
/* @__PURE__ */ jsxs(Flex, { gap: "xs", p: "sm", style: { borderBottom: `0.1vh solid ${alpha(theme2.colors.dark[7], 0.8)}` }, children: [
|
|
4720
5224
|
/* @__PURE__ */ jsx(TextInput, { leftSection: /* @__PURE__ */ jsx(Search, { size: "1.4vh" }), placeholder: "Search path/admin/value", value: queryInput, onChange: (e) => setQueryInput(e.currentTarget.value), size: "xs", style: { flex: 1 } }),
|
|
@@ -4757,7 +5261,7 @@ function ConfigHistoryModal({
|
|
|
4757
5261
|
style: { background: "transparent", border: `0.1vh solid ${theme2.colors.dark[6]}`, borderRadius: theme2.radius.xs, padding: `${theme2.spacing.xxs} ${theme2.spacing.xs}`, cursor: "pointer", display: "flex", alignItems: "center", gap: theme2.spacing.xxs },
|
|
4758
5262
|
children: [
|
|
4759
5263
|
/* @__PURE__ */ jsx(X, { color: "rgba(255,255,255,0.4)", size: "1.5vh" }),
|
|
4760
|
-
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: "rgba(255,255,255,0.4)", children: "
|
|
5264
|
+
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: "rgba(255,255,255,0.4)", children: locale("cfgpanel_close") })
|
|
4761
5265
|
]
|
|
4762
5266
|
}
|
|
4763
5267
|
) })
|
|
@@ -4782,7 +5286,7 @@ function ConfigPanelInner({
|
|
|
4782
5286
|
const theme2 = useMantineTheme();
|
|
4783
5287
|
const color = theme2.colors[theme2.primaryColor][5];
|
|
4784
5288
|
const version = useSettings((s) => s.resourceVersion);
|
|
4785
|
-
const [activeTab, setActiveTab] =
|
|
5289
|
+
const [activeTab, setActiveTab] = useAdminState("__dirkConfigPanel:activeTab", navItems[0]?.id ?? "");
|
|
4786
5290
|
const firstMountRef = useRef(true);
|
|
4787
5291
|
const [jsonOpen, setJsonOpen] = useState(false);
|
|
4788
5292
|
const [historyOpen, setHistoryOpen] = useState(false);
|
|
@@ -4817,16 +5321,16 @@ function ConfigPanelInner({
|
|
|
4817
5321
|
/* @__PURE__ */ jsx(AnimatePresence, { children: resetOpen && /* @__PURE__ */ jsx(
|
|
4818
5322
|
ConfirmModal,
|
|
4819
5323
|
{
|
|
4820
|
-
title: "
|
|
4821
|
-
description: "
|
|
4822
|
-
confirmLabel: "
|
|
5324
|
+
title: locale("cfgpanel_reset_title"),
|
|
5325
|
+
description: locale("cfgpanel_reset_desc"),
|
|
5326
|
+
confirmLabel: locale("cfgpanel_reset_confirm"),
|
|
4823
5327
|
confirmText: resetConfirmText,
|
|
4824
5328
|
onConfirm: async () => {
|
|
4825
5329
|
setResetOpen(false);
|
|
4826
5330
|
const result = await resetConfig();
|
|
4827
5331
|
if (result?.success) {
|
|
4828
|
-
const { store } = getScriptConfigInstance();
|
|
4829
|
-
form.reinitialize(cloneConfig(
|
|
5332
|
+
const { store: store2 } = getScriptConfigInstance();
|
|
5333
|
+
form.reinitialize(cloneConfig(store2.getState()));
|
|
4830
5334
|
notifications.show({
|
|
4831
5335
|
color: "green",
|
|
4832
5336
|
title: locale("ConfigResetSuccessTitle"),
|
|
@@ -4851,9 +5355,9 @@ function ConfigPanelInner({
|
|
|
4851
5355
|
/* @__PURE__ */ jsx(AnimatePresence, { children: pendingAction !== null && /* @__PURE__ */ jsx(
|
|
4852
5356
|
ConfirmModal,
|
|
4853
5357
|
{
|
|
4854
|
-
title: "
|
|
4855
|
-
description: pendingAction === "back" ? "
|
|
4856
|
-
confirmLabel: pendingAction === "back" ? "
|
|
5358
|
+
title: locale("cfgpanel_discard_title"),
|
|
5359
|
+
description: pendingAction === "back" ? locale("cfgpanel_discard_desc_back") : locale("cfgpanel_discard_desc_close"),
|
|
5360
|
+
confirmLabel: pendingAction === "back" ? locale("cfgpanel_discard_confirm_back") : locale("cfgpanel_discard_confirm_close"),
|
|
4857
5361
|
onConfirm: () => {
|
|
4858
5362
|
const action = pendingAction;
|
|
4859
5363
|
setPendingAction(null);
|
|
@@ -4891,7 +5395,7 @@ function ConfigPanelInner({
|
|
|
4891
5395
|
/* @__PURE__ */ jsx(
|
|
4892
5396
|
motion.button,
|
|
4893
5397
|
{
|
|
4894
|
-
title: "
|
|
5398
|
+
title: locale("cfgpanel_back_title"),
|
|
4895
5399
|
onClick: handleBack,
|
|
4896
5400
|
whileHover: { background: alpha(color, 0.16), borderColor: alpha(color, 0.45) },
|
|
4897
5401
|
whileTap: { scale: 0.95 },
|
|
@@ -4919,7 +5423,7 @@ function ConfigPanelInner({
|
|
|
4919
5423
|
/* @__PURE__ */ jsx(
|
|
4920
5424
|
motion.button,
|
|
4921
5425
|
{
|
|
4922
|
-
title: "
|
|
5426
|
+
title: locale("cfgpanel_undo"),
|
|
4923
5427
|
onClick: () => form.canBack && form.back(),
|
|
4924
5428
|
disabled: !form.canBack,
|
|
4925
5429
|
whileHover: form.canBack ? { background: "rgba(255,255,255,0.07)" } : void 0,
|
|
@@ -4931,7 +5435,7 @@ function ConfigPanelInner({
|
|
|
4931
5435
|
/* @__PURE__ */ jsx(
|
|
4932
5436
|
motion.button,
|
|
4933
5437
|
{
|
|
4934
|
-
title: "
|
|
5438
|
+
title: locale("cfgpanel_redo"),
|
|
4935
5439
|
onClick: () => form.canForward && form.forward(),
|
|
4936
5440
|
disabled: !form.canForward,
|
|
4937
5441
|
whileHover: form.canForward ? { background: "rgba(255,255,255,0.07)" } : void 0,
|
|
@@ -4943,7 +5447,7 @@ function ConfigPanelInner({
|
|
|
4943
5447
|
/* @__PURE__ */ jsx(
|
|
4944
5448
|
motion.button,
|
|
4945
5449
|
{
|
|
4946
|
-
title: isSaving ? "
|
|
5450
|
+
title: isSaving ? locale("cfgpanel_saving") : isDirty ? `${locale("cfgpanel_save")} (${changedCount})` : locale("cfgpanel_save"),
|
|
4947
5451
|
onClick: () => isDirty && !isSaving && form.submit(),
|
|
4948
5452
|
disabled: !isDirty || isSaving,
|
|
4949
5453
|
whileHover: isDirty && !isSaving ? { background: alpha(color, 0.25), borderColor: alpha(color, 0.5) } : void 0,
|
|
@@ -4955,7 +5459,7 @@ function ConfigPanelInner({
|
|
|
4955
5459
|
/* @__PURE__ */ jsx(
|
|
4956
5460
|
motion.button,
|
|
4957
5461
|
{
|
|
4958
|
-
title: "
|
|
5462
|
+
title: locale("cfgpanel_history"),
|
|
4959
5463
|
onClick: () => setHistoryOpen(true),
|
|
4960
5464
|
whileHover: { background: alpha("#22d3ee", 0.16), borderColor: alpha("#22d3ee", 0.5) },
|
|
4961
5465
|
whileTap: { scale: 0.97 },
|
|
@@ -4976,7 +5480,7 @@ function ConfigPanelInner({
|
|
|
4976
5480
|
style: { width: "100%", background: "transparent", border: `0.1vh solid ${isDirty ? alpha("#f97316", 0.35) : alpha(theme2.colors.dark[5], 0.3)}`, borderRadius: theme2.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" },
|
|
4977
5481
|
children: [
|
|
4978
5482
|
/* @__PURE__ */ jsx(XCircle, { color: isDirty ? "#f97316" : "rgba(255,255,255,0.35)", size: "1.6vh" }),
|
|
4979
|
-
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: isDirty ? "#f97316" : "rgba(255,255,255,0.35)", children: "
|
|
5483
|
+
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: isDirty ? "#f97316" : "rgba(255,255,255,0.35)", children: locale("cfgpanel_discard") })
|
|
4980
5484
|
]
|
|
4981
5485
|
}
|
|
4982
5486
|
),
|
|
@@ -4990,7 +5494,7 @@ function ConfigPanelInner({
|
|
|
4990
5494
|
style: { width: "100%", background: alpha(color, 0.07), border: `0.1vh solid ${alpha(color, 0.28)}`, borderRadius: theme2.radius.xs, padding: "0.65vh 0.8vh", cursor: "pointer", display: "flex", alignItems: "center", gap: "0.55vh" },
|
|
4991
5495
|
children: [
|
|
4992
5496
|
/* @__PURE__ */ jsx(Code2, { color, size: "1.6vh" }),
|
|
4993
|
-
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: color, children: "
|
|
5497
|
+
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: color, children: locale("cfgpanel_manual_edit") })
|
|
4994
5498
|
]
|
|
4995
5499
|
}
|
|
4996
5500
|
),
|
|
@@ -5003,12 +5507,13 @@ function ConfigPanelInner({
|
|
|
5003
5507
|
style: { width: "100%", background: alpha("#ef4444", 0.07), border: `0.1vh solid ${alpha("#ef4444", 0.25)}`, borderRadius: theme2.radius.xs, padding: "0.65vh 0.8vh", cursor: "pointer", display: "flex", alignItems: "center", gap: "0.55vh" },
|
|
5004
5508
|
children: [
|
|
5005
5509
|
/* @__PURE__ */ jsx(RotateCcw, { color: "#ef4444", size: "1.6vh" }),
|
|
5006
|
-
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: "#ef4444", children: "
|
|
5510
|
+
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: "#ef4444", children: locale("cfgpanel_reset_defaults") })
|
|
5007
5511
|
]
|
|
5008
5512
|
}
|
|
5009
5513
|
),
|
|
5010
5514
|
version && /* @__PURE__ */ jsxs(Text, { size: "0.95vh", c: "dimmed", ta: "center", style: { letterSpacing: "0.04em", opacity: 0.8 }, children: [
|
|
5011
|
-
"
|
|
5515
|
+
locale("cfgpanel_version"),
|
|
5516
|
+
" ",
|
|
5012
5517
|
version
|
|
5013
5518
|
] })
|
|
5014
5519
|
] })
|
|
@@ -5054,13 +5559,13 @@ function ServerOnlyFetcher() {
|
|
|
5054
5559
|
var defaultOnClose = () => fetchNui("CLOSE_ADMIN_SECTION");
|
|
5055
5560
|
function ConfigPanel(props) {
|
|
5056
5561
|
const { open, onClose = defaultOnClose } = props;
|
|
5057
|
-
const { store, updateConfig } = getScriptConfigInstance();
|
|
5562
|
+
const { store: store2, updateConfig } = getScriptConfigInstance();
|
|
5058
5563
|
const [isSaving, setIsSaving] = useState(false);
|
|
5059
5564
|
if (!open) return null;
|
|
5060
|
-
return /* @__PURE__ */ jsx(
|
|
5565
|
+
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
|
|
5061
5566
|
FormProvider,
|
|
5062
5567
|
{
|
|
5063
|
-
initialValues: cloneConfig(
|
|
5568
|
+
initialValues: cloneConfig(store2.getState()),
|
|
5064
5569
|
onSubmit: async (form) => {
|
|
5065
5570
|
if (isSaving) return;
|
|
5066
5571
|
setIsSaving(true);
|
|
@@ -5068,7 +5573,7 @@ function ConfigPanel(props) {
|
|
|
5068
5573
|
const result = await updateConfig(form.values);
|
|
5069
5574
|
if (result?.success) {
|
|
5070
5575
|
form.reinitialize(cloneConfig(form.values));
|
|
5071
|
-
|
|
5576
|
+
dirkQueryClient.invalidateQueries({ queryKey: ["scriptConfigHistory"] });
|
|
5072
5577
|
useMissingItemsAudit.getState().refresh();
|
|
5073
5578
|
notifications.show({
|
|
5074
5579
|
color: "green",
|
|
@@ -5078,7 +5583,7 @@ function ConfigPanel(props) {
|
|
|
5078
5583
|
});
|
|
5079
5584
|
return;
|
|
5080
5585
|
}
|
|
5081
|
-
form.reinitialize(cloneConfig(
|
|
5586
|
+
form.reinitialize(cloneConfig(store2.getState()));
|
|
5082
5587
|
const err = result?._error || "Unknown";
|
|
5083
5588
|
console.warn(`[ConfigPanel] config save failed: ${err}`);
|
|
5084
5589
|
const titleKey = err === "NoPermission" ? "ConfigSaveNoPermissionTitle" : err === "VersionConflict" ? "ConfigSaveVersionConflictTitle" : err === "NotReady" ? "ConfigSaveNotReadyTitle" : "ConfigSaveFailedTitle";
|
|
@@ -5575,6 +6080,9 @@ function GroupName(props) {
|
|
|
5575
6080
|
const ctx = useContext(GroupSelectContext);
|
|
5576
6081
|
const jobs = useFrameworkGroups((s) => s.jobs);
|
|
5577
6082
|
const gangs = useFrameworkGroups((s) => s.gangs);
|
|
6083
|
+
useEffect(() => {
|
|
6084
|
+
ensureFrameworkGroups();
|
|
6085
|
+
}, []);
|
|
5578
6086
|
const inCompound = ctx !== null;
|
|
5579
6087
|
const currentValue = inCompound ? ctx.value.name : props.value;
|
|
5580
6088
|
const filterType = inCompound ? ctx.type : props.type;
|
|
@@ -5614,6 +6122,9 @@ function GroupRank(props) {
|
|
|
5614
6122
|
}
|
|
5615
6123
|
const jobs = useFrameworkGroups((s) => s.jobs);
|
|
5616
6124
|
const gangs = useFrameworkGroups((s) => s.gangs);
|
|
6125
|
+
useEffect(() => {
|
|
6126
|
+
ensureFrameworkGroups();
|
|
6127
|
+
}, []);
|
|
5617
6128
|
const all = [...jobs, ...gangs];
|
|
5618
6129
|
const selectedGroup = all.find((g) => g.name === ctx.value.name) ?? null;
|
|
5619
6130
|
const grades = selectedGroup?.grades ?? [];
|
|
@@ -7259,349 +7770,831 @@ function AccountSelect(props) {
|
|
|
7259
7770
|
!hideFrameworkHint && /* @__PURE__ */ jsx(FrameworkHint, { framework })
|
|
7260
7771
|
] });
|
|
7261
7772
|
}
|
|
7262
|
-
|
|
7263
|
-
|
|
7264
|
-
|
|
7773
|
+
var BODY_HIDE_STYLE_ID2 = "dirk-instruction-panel-style";
|
|
7774
|
+
var BODY_HIDE_ATTR2 = "data-dirk-instruction-active";
|
|
7775
|
+
var OVERLAY_ATTR2 = "data-dirk-instruction-overlay";
|
|
7776
|
+
function ensureBodyHideStyle2() {
|
|
7777
|
+
if (document.getElementById(BODY_HIDE_STYLE_ID2)) return;
|
|
7778
|
+
const el = document.createElement("style");
|
|
7779
|
+
el.id = BODY_HIDE_STYLE_ID2;
|
|
7780
|
+
el.textContent = `
|
|
7781
|
+
body[${BODY_HIDE_ATTR2}] > *:not([${OVERLAY_ATTR2}]) {
|
|
7782
|
+
visibility: hidden !important;
|
|
7783
|
+
opacity: 0 !important;
|
|
7784
|
+
pointer-events: none !important;
|
|
7785
|
+
}
|
|
7786
|
+
`;
|
|
7787
|
+
document.head.appendChild(el);
|
|
7265
7788
|
}
|
|
7266
|
-
function
|
|
7789
|
+
function InstructionPanel({
|
|
7790
|
+
visible,
|
|
7791
|
+
title,
|
|
7792
|
+
hint,
|
|
7793
|
+
keys,
|
|
7794
|
+
icon: Icon = MapPin,
|
|
7795
|
+
hideRestOfAdmin = true
|
|
7796
|
+
}) {
|
|
7797
|
+
const theme2 = useMantineTheme();
|
|
7798
|
+
const pc = theme2.colors[theme2.primaryColor];
|
|
7799
|
+
useEffect(() => {
|
|
7800
|
+
if (!visible || !hideRestOfAdmin) return;
|
|
7801
|
+
ensureBodyHideStyle2();
|
|
7802
|
+
document.body.setAttribute(BODY_HIDE_ATTR2, "");
|
|
7803
|
+
return () => {
|
|
7804
|
+
document.body.removeAttribute(BODY_HIDE_ATTR2);
|
|
7805
|
+
};
|
|
7806
|
+
}, [visible, hideRestOfAdmin]);
|
|
7807
|
+
if (!visible) return null;
|
|
7808
|
+
return createPortal(
|
|
7809
|
+
/* @__PURE__ */ jsx(
|
|
7810
|
+
"div",
|
|
7811
|
+
{
|
|
7812
|
+
...{ [OVERLAY_ATTR2]: "" },
|
|
7813
|
+
style: { position: "fixed", inset: 0, pointerEvents: "none", zIndex: 1e4 },
|
|
7814
|
+
children: /* @__PURE__ */ jsx(AnimatePresence, { children: /* @__PURE__ */ jsx(
|
|
7815
|
+
motion.div,
|
|
7816
|
+
{
|
|
7817
|
+
initial: { opacity: 0, y: 12, scale: 0.92 },
|
|
7818
|
+
animate: { opacity: 1, y: 0, scale: 1 },
|
|
7819
|
+
exit: { opacity: 0, y: 12, scale: 0.92 },
|
|
7820
|
+
transition: { duration: 0.25, ease: "easeInOut" },
|
|
7821
|
+
style: { position: "absolute", bottom: "3vh", right: "3vh", userSelect: "none" },
|
|
7822
|
+
children: /* @__PURE__ */ jsxs(
|
|
7823
|
+
Flex,
|
|
7824
|
+
{
|
|
7825
|
+
direction: "column",
|
|
7826
|
+
gap: "0.8vh",
|
|
7827
|
+
style: {
|
|
7828
|
+
background: alpha(theme2.colors.dark[9], 0.55),
|
|
7829
|
+
border: "0.1vh solid rgba(255,255,255,0.07)",
|
|
7830
|
+
borderRadius: theme2.radius.sm,
|
|
7831
|
+
boxShadow: "0 0.74vh 2.96vh rgba(0,0,0,0.5)",
|
|
7832
|
+
padding: "1.4vh 1.6vh",
|
|
7833
|
+
minWidth: "22vh",
|
|
7834
|
+
maxWidth: "28vh"
|
|
7835
|
+
},
|
|
7836
|
+
children: [
|
|
7837
|
+
/* @__PURE__ */ jsxs(Flex, { align: "center", gap: "0.6vh", children: [
|
|
7838
|
+
/* @__PURE__ */ jsx(Icon, { size: "1.6vh", color: pc[6], strokeWidth: 2.5 }),
|
|
7839
|
+
/* @__PURE__ */ jsx(
|
|
7840
|
+
Text,
|
|
7841
|
+
{
|
|
7842
|
+
style: {
|
|
7843
|
+
fontFamily: "Akrobat Bold, sans-serif",
|
|
7844
|
+
fontSize: "1.7vh",
|
|
7845
|
+
fontWeight: 700,
|
|
7846
|
+
letterSpacing: "0.14em",
|
|
7847
|
+
textTransform: "uppercase",
|
|
7848
|
+
color: pc[6],
|
|
7849
|
+
textShadow: `0 0 0.8vh ${alpha(pc[7], 0.5)}, 0 0 1.6vh ${alpha(pc[9], 0.3)}`
|
|
7850
|
+
},
|
|
7851
|
+
children: title
|
|
7852
|
+
}
|
|
7853
|
+
)
|
|
7854
|
+
] }),
|
|
7855
|
+
(hint || keys && keys.length > 0) && /* @__PURE__ */ jsx("div", { style: { height: "0.1vh", background: "rgba(255,255,255,0.06)", margin: "0.1vh 0" } }),
|
|
7856
|
+
hint && /* @__PURE__ */ jsx(
|
|
7857
|
+
Text,
|
|
7858
|
+
{
|
|
7859
|
+
style: {
|
|
7860
|
+
fontFamily: "Akrobat Bold, sans-serif",
|
|
7861
|
+
fontSize: "1.05vh",
|
|
7862
|
+
color: "rgba(255,255,255,0.45)",
|
|
7863
|
+
letterSpacing: "0.06em",
|
|
7864
|
+
textTransform: "uppercase",
|
|
7865
|
+
lineHeight: 1.4
|
|
7866
|
+
},
|
|
7867
|
+
children: hint
|
|
7868
|
+
}
|
|
7869
|
+
),
|
|
7870
|
+
keys && keys.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7871
|
+
hint && /* @__PURE__ */ jsx("div", { style: { height: "0.1vh", background: "rgba(255,255,255,0.06)", margin: "0.1vh 0" } }),
|
|
7872
|
+
/* @__PURE__ */ jsx(Flex, { direction: "column", gap: "0.5vh", children: keys.map((k, i) => /* @__PURE__ */ jsx(InstructionKeyRow, { keyLabel: k.key, action: k.action }, i)) })
|
|
7873
|
+
] })
|
|
7874
|
+
]
|
|
7875
|
+
}
|
|
7876
|
+
)
|
|
7877
|
+
},
|
|
7878
|
+
"instruction-card"
|
|
7879
|
+
) })
|
|
7880
|
+
}
|
|
7881
|
+
),
|
|
7882
|
+
document.body
|
|
7883
|
+
);
|
|
7884
|
+
}
|
|
7885
|
+
function renderKeyContent(keyLabel) {
|
|
7886
|
+
const normalized = keyLabel.trim().toUpperCase();
|
|
7887
|
+
if (normalized === "LMB") return /* @__PURE__ */ jsx(MouseIcon, { side: "left" });
|
|
7888
|
+
if (normalized === "RMB") return /* @__PURE__ */ jsx(MouseIcon, { side: "right" });
|
|
7889
|
+
if (normalized === "BACKSPACE" || keyLabel === "\u232B") return /* @__PURE__ */ jsx(BackspaceIcon, {});
|
|
7267
7890
|
return /* @__PURE__ */ jsx(
|
|
7268
|
-
|
|
7891
|
+
Text,
|
|
7269
7892
|
{
|
|
7270
|
-
style: {
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
numOctaves: "5",
|
|
7279
|
-
seed: "9",
|
|
7280
|
-
result: "noise1"
|
|
7281
|
-
}
|
|
7282
|
-
),
|
|
7283
|
-
/* @__PURE__ */ jsx(
|
|
7284
|
-
"feTurbulence",
|
|
7285
|
-
{
|
|
7286
|
-
type: "fractalNoise",
|
|
7287
|
-
baseFrequency: "0.08 0.12",
|
|
7288
|
-
numOctaves: "2",
|
|
7289
|
-
seed: "3",
|
|
7290
|
-
result: "noise2"
|
|
7291
|
-
}
|
|
7292
|
-
),
|
|
7293
|
-
/* @__PURE__ */ jsx("feBlend", { in: "noise1", in2: "noise2", mode: "multiply", result: "combinedNoise" }),
|
|
7294
|
-
/* @__PURE__ */ jsx(
|
|
7295
|
-
"feDisplacementMap",
|
|
7296
|
-
{
|
|
7297
|
-
in: "SourceGraphic",
|
|
7298
|
-
in2: "combinedNoise",
|
|
7299
|
-
scale: "52",
|
|
7300
|
-
xChannelSelector: "R",
|
|
7301
|
-
yChannelSelector: "G",
|
|
7302
|
-
result: "displaced"
|
|
7303
|
-
}
|
|
7304
|
-
),
|
|
7305
|
-
/* @__PURE__ */ jsx("feGaussianBlur", { stdDeviation: "0.8", in: "displaced", result: "blurred" }),
|
|
7306
|
-
/* @__PURE__ */ jsx("feComponentTransfer", { in: "blurred", result: "alphaFade", children: /* @__PURE__ */ jsx("feFuncA", { type: "gamma", amplitude: "1", exponent: "1.3", offset: "-0.05" }) }),
|
|
7307
|
-
/* @__PURE__ */ jsx("feMorphology", { operator: "erode", radius: "0.4", in: "alphaFade", result: "eroded" }),
|
|
7308
|
-
/* @__PURE__ */ jsx("feMerge", { children: /* @__PURE__ */ jsx("feMergeNode", { in: "eroded" }) })
|
|
7309
|
-
] }) })
|
|
7893
|
+
style: {
|
|
7894
|
+
fontFamily: "Akrobat Bold, sans-serif",
|
|
7895
|
+
fontSize: "1.2vh",
|
|
7896
|
+
color: "rgba(255,255,255,0.85)",
|
|
7897
|
+
lineHeight: 1,
|
|
7898
|
+
padding: "0 0.3vh"
|
|
7899
|
+
},
|
|
7900
|
+
children: keyLabel
|
|
7310
7901
|
}
|
|
7311
7902
|
);
|
|
7312
7903
|
}
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
sm: "0.75vh",
|
|
7348
|
-
md: "1vh",
|
|
7349
|
-
lg: "1.5vh",
|
|
7350
|
-
xl: "2vh",
|
|
7351
|
-
xxl: "3vh"
|
|
7352
|
-
},
|
|
7353
|
-
fontSizes: {
|
|
7354
|
-
xxs: "1.2vh",
|
|
7355
|
-
xs: "1.5vh",
|
|
7356
|
-
sm: "1.8vh",
|
|
7357
|
-
md: "2.2vh",
|
|
7358
|
-
lg: "2.8vh",
|
|
7359
|
-
xl: "3.3vh",
|
|
7360
|
-
xxl: "3.8vh"
|
|
7361
|
-
},
|
|
7362
|
-
lineHeights: {
|
|
7363
|
-
xxs: "1.4vh",
|
|
7364
|
-
xs: "1.8vh",
|
|
7365
|
-
sm: "2.2vh",
|
|
7366
|
-
md: "2.8vh",
|
|
7367
|
-
lg: "3.3vh",
|
|
7368
|
-
xl: "3.8vh"
|
|
7369
|
-
},
|
|
7370
|
-
spacing: {
|
|
7371
|
-
xxs: "0.5vh",
|
|
7372
|
-
xs: "0.75vh",
|
|
7373
|
-
sm: "1.5vh",
|
|
7374
|
-
md: "2vh",
|
|
7375
|
-
lg: "3vh",
|
|
7376
|
-
xl: "4vh",
|
|
7377
|
-
xxl: "5vh"
|
|
7378
|
-
},
|
|
7379
|
-
components: {
|
|
7380
|
-
Progress: {
|
|
7381
|
-
styles: {
|
|
7382
|
-
label: {
|
|
7383
|
-
fontFamily: "Akrobat Bold",
|
|
7384
|
-
letterSpacing: "0.05em",
|
|
7904
|
+
function InstructionKeyRow({ keyLabel, action }) {
|
|
7905
|
+
const normalized = keyLabel.trim().toUpperCase();
|
|
7906
|
+
const isIconKey = normalized === "LMB" || normalized === "RMB" || normalized === "BACKSPACE" || keyLabel === "\u232B";
|
|
7907
|
+
const minWidth = isIconKey ? "2.6vh" : "2.4vh";
|
|
7908
|
+
return /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "0.6vh", children: [
|
|
7909
|
+
/* @__PURE__ */ jsx(
|
|
7910
|
+
"div",
|
|
7911
|
+
{
|
|
7912
|
+
style: {
|
|
7913
|
+
minWidth,
|
|
7914
|
+
height: "2.4vh",
|
|
7915
|
+
padding: "0 0.4vh",
|
|
7916
|
+
borderRadius: "0.3vh",
|
|
7917
|
+
border: "0.15vh solid rgba(255,255,255,0.35)",
|
|
7918
|
+
background: "rgba(255,255,255,0.06)",
|
|
7919
|
+
display: "flex",
|
|
7920
|
+
alignItems: "center",
|
|
7921
|
+
justifyContent: "center",
|
|
7922
|
+
opacity: 0.85,
|
|
7923
|
+
filter: "drop-shadow(0 0 0.3vh rgba(0,0,0,0.5))",
|
|
7924
|
+
flexShrink: 0,
|
|
7925
|
+
boxSizing: "border-box"
|
|
7926
|
+
},
|
|
7927
|
+
children: renderKeyContent(keyLabel)
|
|
7928
|
+
}
|
|
7929
|
+
),
|
|
7930
|
+
/* @__PURE__ */ jsx(
|
|
7931
|
+
Text,
|
|
7932
|
+
{
|
|
7933
|
+
style: {
|
|
7934
|
+
fontFamily: "Akrobat Bold, sans-serif",
|
|
7935
|
+
fontSize: "1.05vh",
|
|
7936
|
+
color: "rgba(255,255,255,0.45)",
|
|
7937
|
+
letterSpacing: "0.06em",
|
|
7385
7938
|
textTransform: "uppercase"
|
|
7386
7939
|
},
|
|
7387
|
-
|
|
7388
|
-
backgroundColor: "rgba(77, 77, 77, 0.4)"
|
|
7389
|
-
}
|
|
7940
|
+
children: action
|
|
7390
7941
|
}
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
|
|
7394
|
-
|
|
7395
|
-
|
|
7396
|
-
|
|
7397
|
-
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7942
|
+
)
|
|
7943
|
+
] });
|
|
7944
|
+
}
|
|
7945
|
+
function MouseIcon({ side }) {
|
|
7946
|
+
const stroke = "rgba(255,255,255,0.85)";
|
|
7947
|
+
const fillActive = "rgba(255,255,255,0.85)";
|
|
7948
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 22", width: "1.4vh", height: "1.9vh", fill: "none", stroke, strokeWidth: "1.4", strokeLinejoin: "round", children: [
|
|
7949
|
+
/* @__PURE__ */ jsx("rect", { x: "1", y: "1", width: "14", height: "20", rx: "6" }),
|
|
7950
|
+
/* @__PURE__ */ jsx("line", { x1: "8", y1: "1", x2: "8", y2: "9" }),
|
|
7951
|
+
/* @__PURE__ */ jsx(
|
|
7952
|
+
"path",
|
|
7953
|
+
{
|
|
7954
|
+
d: side === "left" ? "M 7.4 1.6 L 2 1.6 A 5 5 0 0 0 1 6 L 1 9 L 7.4 9 Z" : "M 8.6 1.6 L 14 1.6 A 5 5 0 0 1 15 6 L 15 9 L 8.6 9 Z",
|
|
7955
|
+
fill: fillActive,
|
|
7956
|
+
stroke: "none"
|
|
7957
|
+
}
|
|
7958
|
+
)
|
|
7959
|
+
] });
|
|
7960
|
+
}
|
|
7961
|
+
function BackspaceIcon() {
|
|
7962
|
+
const stroke = "rgba(255,255,255,0.85)";
|
|
7963
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 22 16", width: "1.7vh", height: "1.3vh", fill: "none", stroke, strokeWidth: "1.4", strokeLinejoin: "round", strokeLinecap: "round", children: [
|
|
7964
|
+
/* @__PURE__ */ jsx("path", { d: "M 21 2 L 8 2 L 2 8 L 8 14 L 21 14 Z" }),
|
|
7965
|
+
/* @__PURE__ */ jsx("line", { x1: "11", y1: "6", x2: "16", y2: "11" }),
|
|
7966
|
+
/* @__PURE__ */ jsx("line", { x1: "16", y1: "6", x2: "11", y2: "11" })
|
|
7967
|
+
] });
|
|
7968
|
+
}
|
|
7969
|
+
function WorldPositionPicker({ value, onChange, compact, setOnly, gotoOnly }) {
|
|
7970
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7971
|
+
!gotoOnly && /* @__PURE__ */ jsx(WorldPositionSetButton2, { value, onChange, compact }),
|
|
7972
|
+
!setOnly && /* @__PURE__ */ jsx(WorldPositionGotoButton2, { value, compact })
|
|
7973
|
+
] });
|
|
7974
|
+
}
|
|
7975
|
+
function WorldPositionSetButton2({
|
|
7976
|
+
value,
|
|
7977
|
+
onChange,
|
|
7978
|
+
compact
|
|
7979
|
+
}) {
|
|
7980
|
+
const theme2 = useMantineTheme();
|
|
7981
|
+
const color = theme2.colors[theme2.primaryColor][5];
|
|
7982
|
+
const begin = useAdminToolStore((s) => s.begin);
|
|
7983
|
+
const onClick = async () => {
|
|
7984
|
+
const instructions = {
|
|
7985
|
+
title: locale("PickPositionTitle") || "Pick Position",
|
|
7986
|
+
hint: locale("PickPositionHint") || "Walk to where you want this set",
|
|
7987
|
+
keys: [
|
|
7988
|
+
{ key: "E", action: locale("Set") || "Set" },
|
|
7989
|
+
{ key: "\u232B", action: locale("Cancel") || "Cancel" }
|
|
7990
|
+
]
|
|
7991
|
+
};
|
|
7992
|
+
const pendingResult = begin({ id: "capturePosition", ...instructions });
|
|
7993
|
+
fetchNui("ADMIN_TOOL_BEGIN", { id: "capturePosition", instructions }).catch(() => {
|
|
7994
|
+
useAdminToolStore.getState().cancelActive();
|
|
7995
|
+
});
|
|
7996
|
+
const result = await pendingResult;
|
|
7997
|
+
if (result) onChange(result);
|
|
7998
|
+
};
|
|
7999
|
+
return /* @__PURE__ */ jsx(Tooltip, { label: locale("SetWorldTooltip"), position: "top", withArrow: true, withinPortal: true, zIndex: 2e3, children: /* @__PURE__ */ jsxs(
|
|
8000
|
+
motion.button,
|
|
8001
|
+
{
|
|
8002
|
+
onClick,
|
|
8003
|
+
whileHover: { background: alpha(color, 0.18) },
|
|
8004
|
+
whileTap: { scale: 0.95 },
|
|
8005
|
+
style: {
|
|
8006
|
+
background: alpha(color, 0.1),
|
|
8007
|
+
border: `0.1vh solid ${alpha(color, 0.35)}`,
|
|
8008
|
+
borderRadius: theme2.radius.xs,
|
|
8009
|
+
padding: compact ? "0.25vh 0.6vh" : "0.5vh 0.8vh",
|
|
8010
|
+
cursor: "pointer",
|
|
8011
|
+
display: "flex",
|
|
8012
|
+
alignItems: "center",
|
|
8013
|
+
gap: compact ? "0.3vh" : "0.4vh"
|
|
8014
|
+
},
|
|
8015
|
+
children: [
|
|
8016
|
+
/* @__PURE__ */ jsx(Crosshair, { size: compact ? "1.1vh" : "1.3vh", color }),
|
|
8017
|
+
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: color, children: locale("Set") })
|
|
8018
|
+
]
|
|
7417
8019
|
}
|
|
7418
|
-
}
|
|
7419
|
-
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
8020
|
+
) });
|
|
8021
|
+
}
|
|
8022
|
+
function WorldPositionGotoButton2({
|
|
8023
|
+
value,
|
|
8024
|
+
compact
|
|
8025
|
+
}) {
|
|
8026
|
+
const theme2 = useMantineTheme();
|
|
8027
|
+
const color = theme2.colors[theme2.primaryColor][5];
|
|
8028
|
+
const onClick = () => {
|
|
8029
|
+
fetchNui("ADMIN_TOOL_INVOKE", { id: "gotoCoord", value }).catch(() => {
|
|
8030
|
+
});
|
|
8031
|
+
};
|
|
8032
|
+
return /* @__PURE__ */ jsx(Tooltip, { label: locale("GotoWorldTooltip"), position: "top", withArrow: true, withinPortal: true, zIndex: 2e3, children: /* @__PURE__ */ jsxs(
|
|
8033
|
+
motion.button,
|
|
8034
|
+
{
|
|
8035
|
+
onClick,
|
|
8036
|
+
whileHover: { background: alpha(color, 0.18) },
|
|
8037
|
+
whileTap: { scale: 0.95 },
|
|
8038
|
+
style: {
|
|
8039
|
+
background: alpha(color, 0.1),
|
|
8040
|
+
border: `0.1vh solid ${alpha(color, 0.35)}`,
|
|
8041
|
+
borderRadius: theme2.radius.xs,
|
|
8042
|
+
padding: compact ? "0.25vh 0.6vh" : "0.5vh 0.8vh",
|
|
8043
|
+
cursor: "pointer",
|
|
8044
|
+
display: "flex",
|
|
8045
|
+
alignItems: "center",
|
|
8046
|
+
gap: compact ? "0.3vh" : "0.4vh"
|
|
8047
|
+
},
|
|
8048
|
+
children: [
|
|
8049
|
+
/* @__PURE__ */ jsx(MapPin, { size: compact ? "1.1vh" : "1.3vh", color }),
|
|
8050
|
+
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: color, children: locale("Goto") })
|
|
8051
|
+
]
|
|
7446
8052
|
}
|
|
7447
|
-
}
|
|
8053
|
+
) });
|
|
8054
|
+
}
|
|
8055
|
+
function usePlayers(opts = {}) {
|
|
8056
|
+
const {
|
|
8057
|
+
includeOffline = false,
|
|
8058
|
+
search = "",
|
|
8059
|
+
limit = 50,
|
|
8060
|
+
staleTimeMs,
|
|
8061
|
+
refetchIntervalMs
|
|
8062
|
+
} = opts;
|
|
8063
|
+
const query = useQuery({
|
|
8064
|
+
queryKey: includeOffline ? ["dirk:players", "search", search.trim().toLowerCase(), limit] : ["dirk:players", "online"],
|
|
8065
|
+
queryFn: async () => {
|
|
8066
|
+
const toolId = includeOffline ? "searchPlayers" : "getOnlinePlayers";
|
|
8067
|
+
const payload = includeOffline ? { id: toolId, value: { search: search.trim(), limit } } : { id: toolId };
|
|
8068
|
+
const result = await fetchNui(
|
|
8069
|
+
"ADMIN_TOOL_QUERY",
|
|
8070
|
+
payload,
|
|
8071
|
+
// Browser-dev fallback. Returns a couple of mock players so the
|
|
8072
|
+
// dev shell isn't blank.
|
|
8073
|
+
includeOffline ? [
|
|
8074
|
+
{ id: 1, citizenId: "ABC12345", name: "Dev User", charName: "John Doe", online: true },
|
|
8075
|
+
{ id: null, citizenId: "DEF67890", name: "", charName: "Jane Offline", online: false }
|
|
8076
|
+
] : [
|
|
8077
|
+
{ id: 1, citizenId: "ABC12345", name: "Dev User", charName: "John Doe", online: true }
|
|
8078
|
+
]
|
|
8079
|
+
);
|
|
8080
|
+
return Array.isArray(result) ? result : [];
|
|
8081
|
+
},
|
|
8082
|
+
staleTime: staleTimeMs ?? (includeOffline ? 3e4 : 5e3),
|
|
8083
|
+
gcTime: 5 * 6e4,
|
|
8084
|
+
refetchInterval: refetchIntervalMs ?? false,
|
|
8085
|
+
refetchOnWindowFocus: false,
|
|
8086
|
+
placeholderData: includeOffline ? keepPreviousData : void 0
|
|
8087
|
+
});
|
|
7448
8088
|
return {
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
8089
|
+
players: query.data ?? [],
|
|
8090
|
+
isLoading: query.isLoading,
|
|
8091
|
+
isFetching: query.isFetching,
|
|
8092
|
+
error: query.error ?? null,
|
|
8093
|
+
refresh: () => query.refetch()
|
|
8094
|
+
};
|
|
8095
|
+
}
|
|
8096
|
+
var DEBOUNCE_MS = 300;
|
|
8097
|
+
var ONLINE_COLOR = "#3FA83F";
|
|
8098
|
+
var OFFLINE_COLOR = "#E54141";
|
|
8099
|
+
function PlayerSelect({
|
|
8100
|
+
value,
|
|
8101
|
+
onChange,
|
|
8102
|
+
includeOffline = false,
|
|
8103
|
+
limit = 50,
|
|
8104
|
+
searchable: searchableProp,
|
|
8105
|
+
placeholder,
|
|
8106
|
+
nothingFoundMessage: nothingFoundMessageProp,
|
|
8107
|
+
loadingLabel = "Loading\u2026",
|
|
8108
|
+
onlineLabel = "Online",
|
|
8109
|
+
offlineLabel = "Offline",
|
|
8110
|
+
refreshLabel = "Refresh player list",
|
|
8111
|
+
...rest
|
|
8112
|
+
}) {
|
|
8113
|
+
const theme2 = useMantineTheme();
|
|
8114
|
+
const color = theme2.colors[theme2.primaryColor][5];
|
|
8115
|
+
const [searchInput, setSearchInput] = useState("");
|
|
8116
|
+
const [debouncedSearch, setDebouncedSearch] = useState("");
|
|
8117
|
+
const { players, isFetching, refresh } = usePlayers({
|
|
8118
|
+
includeOffline,
|
|
8119
|
+
search: includeOffline ? debouncedSearch : void 0,
|
|
8120
|
+
limit
|
|
8121
|
+
});
|
|
8122
|
+
const sortedPlayers = useMemo(
|
|
8123
|
+
() => [...players].sort((a, b) => {
|
|
8124
|
+
if (a.online !== b.online) return a.online ? -1 : 1;
|
|
8125
|
+
return a.charName.localeCompare(b.charName);
|
|
8126
|
+
}),
|
|
8127
|
+
[players]
|
|
8128
|
+
);
|
|
8129
|
+
const playerByCitizen = useMemo(() => {
|
|
8130
|
+
const m = /* @__PURE__ */ new Map();
|
|
8131
|
+
for (const p of sortedPlayers) m.set(p.citizenId, p);
|
|
8132
|
+
return m;
|
|
8133
|
+
}, [sortedPlayers]);
|
|
8134
|
+
const data = useMemo(() => {
|
|
8135
|
+
const items = sortedPlayers.map((p) => ({
|
|
8136
|
+
value: p.citizenId,
|
|
8137
|
+
label: formatLabel(p)
|
|
8138
|
+
}));
|
|
8139
|
+
if (value && !items.some((i) => i.value === value)) {
|
|
8140
|
+
items.unshift({ value, label: value });
|
|
7454
8141
|
}
|
|
8142
|
+
return items;
|
|
8143
|
+
}, [sortedPlayers, value]);
|
|
8144
|
+
const selectedPlayer = value ? playerByCitizen.get(value) ?? null : null;
|
|
8145
|
+
const selectedLabel = selectedPlayer ? formatLabel(selectedPlayer) : null;
|
|
8146
|
+
useEffect(() => {
|
|
8147
|
+
if (!includeOffline) return;
|
|
8148
|
+
if (selectedLabel && searchInput === selectedLabel) return;
|
|
8149
|
+
const t3 = setTimeout(() => setDebouncedSearch(searchInput), DEBOUNCE_MS);
|
|
8150
|
+
return () => clearTimeout(t3);
|
|
8151
|
+
}, [searchInput, includeOffline, selectedLabel]);
|
|
8152
|
+
const renderOption = ({ option }) => {
|
|
8153
|
+
const p = playerByCitizen.get(option.value);
|
|
8154
|
+
if (!p) return option.label;
|
|
8155
|
+
return /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", gap: "xs", style: { width: "100%" }, children: [
|
|
8156
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", truncate: true, style: { flex: 1 }, children: formatLabel(p) }),
|
|
8157
|
+
/* @__PURE__ */ jsx(StatusDot, { online: p.online, onlineLabel, offlineLabel })
|
|
8158
|
+
] });
|
|
7455
8159
|
};
|
|
8160
|
+
return /* @__PURE__ */ jsx(
|
|
8161
|
+
Select,
|
|
8162
|
+
{
|
|
8163
|
+
...rest,
|
|
8164
|
+
data,
|
|
8165
|
+
value: value ?? null,
|
|
8166
|
+
onChange: (v) => {
|
|
8167
|
+
if (!v) return onChange(null);
|
|
8168
|
+
const player = playerByCitizen.get(v) ?? null;
|
|
8169
|
+
onChange(player);
|
|
8170
|
+
},
|
|
8171
|
+
searchable: searchableProp ?? true,
|
|
8172
|
+
searchValue: includeOffline ? searchInput : void 0,
|
|
8173
|
+
onSearchChange: includeOffline ? setSearchInput : void 0,
|
|
8174
|
+
placeholder,
|
|
8175
|
+
nothingFoundMessage: isFetching ? loadingLabel : nothingFoundMessageProp ?? "No players found",
|
|
8176
|
+
maxDropdownHeight: 300,
|
|
8177
|
+
renderOption,
|
|
8178
|
+
leftSection: selectedPlayer ? /* @__PURE__ */ jsx(StatusDot, { online: selectedPlayer.online, onlineLabel, offlineLabel }) : void 0,
|
|
8179
|
+
rightSectionWidth: "3.5vh",
|
|
8180
|
+
rightSectionPointerEvents: "all",
|
|
8181
|
+
rightSection: /* @__PURE__ */ jsx(
|
|
8182
|
+
ActionIcon,
|
|
8183
|
+
{
|
|
8184
|
+
variant: "subtle",
|
|
8185
|
+
size: "sm",
|
|
8186
|
+
onClick: (e) => {
|
|
8187
|
+
e.stopPropagation();
|
|
8188
|
+
refresh();
|
|
8189
|
+
},
|
|
8190
|
+
"aria-label": refreshLabel,
|
|
8191
|
+
title: refreshLabel,
|
|
8192
|
+
style: { marginRight: "0.6vh" },
|
|
8193
|
+
children: isFetching ? /* @__PURE__ */ jsx(Loader, { size: "1.2vh", color }) : /* @__PURE__ */ jsx(RefreshCw, { size: "1.4vh", color })
|
|
8194
|
+
}
|
|
8195
|
+
)
|
|
8196
|
+
}
|
|
8197
|
+
);
|
|
7456
8198
|
}
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
}
|
|
7471
|
-
render() {
|
|
7472
|
-
if (!this.state.error) return this.props.children;
|
|
7473
|
-
return /* @__PURE__ */ jsx(
|
|
7474
|
-
Box,
|
|
7475
|
-
{
|
|
7476
|
-
style: {
|
|
7477
|
-
position: "fixed",
|
|
7478
|
-
inset: 0,
|
|
7479
|
-
width: "100vw",
|
|
7480
|
-
height: "100vh",
|
|
7481
|
-
background: "rgba(10, 10, 12, 0.92)",
|
|
7482
|
-
display: "flex",
|
|
7483
|
-
alignItems: "center",
|
|
7484
|
-
justifyContent: "center",
|
|
7485
|
-
padding: "2rem",
|
|
7486
|
-
zIndex: 999999
|
|
7487
|
-
},
|
|
7488
|
-
children: /* @__PURE__ */ jsx(
|
|
7489
|
-
Box,
|
|
7490
|
-
{
|
|
7491
|
-
maw: 900,
|
|
7492
|
-
w: "100%",
|
|
7493
|
-
p: "lg",
|
|
7494
|
-
style: {
|
|
7495
|
-
background: "rgba(20,20,24,0.75)",
|
|
7496
|
-
border: "1px solid rgba(255,255,255,0.08)",
|
|
7497
|
-
borderRadius: "10px",
|
|
7498
|
-
boxShadow: "0 10px 40px rgba(0,0,0,0.6)"
|
|
7499
|
-
},
|
|
7500
|
-
children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
7501
|
-
/* @__PURE__ */ jsx(Title$1, { order: 2, c: "red.5", children: "Dirk UI Crash" }),
|
|
7502
|
-
/* @__PURE__ */ jsx(Text, { c: "dimmed", size: "sm", children: "The interface encountered a fatal error and stopped rendering." }),
|
|
7503
|
-
/* @__PURE__ */ jsx(Code, { block: true, style: { maxHeight: 150, overflow: "auto" }, children: this.state.error?.message }),
|
|
7504
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Check console for full stack trace" })
|
|
7505
|
-
] })
|
|
7506
|
-
}
|
|
7507
|
-
)
|
|
8199
|
+
function StatusDot({ online, onlineLabel, offlineLabel }) {
|
|
8200
|
+
return /* @__PURE__ */ jsx(
|
|
8201
|
+
"span",
|
|
8202
|
+
{
|
|
8203
|
+
title: online ? onlineLabel : offlineLabel,
|
|
8204
|
+
style: {
|
|
8205
|
+
display: "inline-block",
|
|
8206
|
+
width: "0.9vh",
|
|
8207
|
+
height: "0.9vh",
|
|
8208
|
+
borderRadius: "50%",
|
|
8209
|
+
backgroundColor: online ? ONLINE_COLOR : OFFLINE_COLOR,
|
|
8210
|
+
boxShadow: `0 0 0.4vh ${online ? ONLINE_COLOR : OFFLINE_COLOR}`,
|
|
8211
|
+
flexShrink: 0
|
|
7508
8212
|
}
|
|
7509
|
-
|
|
8213
|
+
}
|
|
8214
|
+
);
|
|
8215
|
+
}
|
|
8216
|
+
function formatLabel(p) {
|
|
8217
|
+
const parts = [p.charName || p.citizenId];
|
|
8218
|
+
if (p.online) {
|
|
8219
|
+
if (p.name) parts.push(p.name);
|
|
8220
|
+
if (p.id != null) parts.push(`#${p.id}`);
|
|
7510
8221
|
}
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
function
|
|
7514
|
-
const
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
|
|
7525
|
-
});
|
|
7526
|
-
}, [overideResourceName]);
|
|
7527
|
-
useEffect(() => {
|
|
7528
|
-
fetchNui("NUI_READY").catch(() => {
|
|
8222
|
+
return parts.join(" \xB7 ");
|
|
8223
|
+
}
|
|
8224
|
+
function usePickDoor() {
|
|
8225
|
+
const begin = useAdminToolStore((s) => s.begin);
|
|
8226
|
+
return async () => {
|
|
8227
|
+
const pending = begin({
|
|
8228
|
+
id: "pickDoor",
|
|
8229
|
+
title: locale("PickDoorTitle"),
|
|
8230
|
+
hint: locale("PickDoorHint"),
|
|
8231
|
+
keys: [
|
|
8232
|
+
{ key: "LMB", action: locale("Toggle") },
|
|
8233
|
+
{ key: "E", action: locale("Confirm") },
|
|
8234
|
+
{ key: "BACKSPACE", action: locale("Cancel") }
|
|
8235
|
+
]
|
|
7529
8236
|
});
|
|
7530
|
-
|
|
7531
|
-
|
|
7532
|
-
fetchNui("GET_RESOURCE_VERSION", void 0, { version: "dev" })
|
|
7533
|
-
]).then(([data, resourceInfo]) => {
|
|
7534
|
-
useSettings.setState({
|
|
7535
|
-
...data,
|
|
7536
|
-
resourceVersion: resourceInfo?.version || "dev"
|
|
7537
|
-
});
|
|
7538
|
-
}).catch((err) => {
|
|
7539
|
-
console.error("Failed to fetch initial settings within dirk-cfx-react:", err);
|
|
8237
|
+
fetchNui("ADMIN_TOOL_BEGIN", { id: "pickDoor" }).catch(() => {
|
|
8238
|
+
useAdminToolStore.getState().cancelActive();
|
|
7540
8239
|
});
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
7544
|
-
|
|
7545
|
-
|
|
7546
|
-
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
8240
|
+
return await pending;
|
|
8241
|
+
};
|
|
8242
|
+
}
|
|
8243
|
+
function DoorPickerButton({
|
|
8244
|
+
onPick,
|
|
8245
|
+
compact,
|
|
8246
|
+
label: label2,
|
|
8247
|
+
tooltip
|
|
8248
|
+
}) {
|
|
8249
|
+
const theme2 = useMantineTheme();
|
|
8250
|
+
const color = theme2.colors[theme2.primaryColor][5];
|
|
8251
|
+
const pickDoor = usePickDoor();
|
|
8252
|
+
const onClick = async () => {
|
|
8253
|
+
const picked = await pickDoor();
|
|
8254
|
+
if (picked && picked.doors.length > 0) onPick(picked);
|
|
8255
|
+
};
|
|
8256
|
+
return /* @__PURE__ */ jsx(
|
|
8257
|
+
Tooltip,
|
|
8258
|
+
{
|
|
8259
|
+
label: tooltip ?? locale("PickDoorTooltip"),
|
|
8260
|
+
position: "top",
|
|
8261
|
+
withArrow: true,
|
|
8262
|
+
withinPortal: true,
|
|
8263
|
+
zIndex: 2e3,
|
|
8264
|
+
children: /* @__PURE__ */ jsxs(
|
|
8265
|
+
motion.button,
|
|
8266
|
+
{
|
|
8267
|
+
onClick,
|
|
8268
|
+
whileHover: { background: alpha(color, 0.18) },
|
|
8269
|
+
whileTap: { scale: 0.95 },
|
|
8270
|
+
style: {
|
|
8271
|
+
background: alpha(color, 0.1),
|
|
8272
|
+
border: `0.1vh solid ${alpha(color, 0.35)}`,
|
|
8273
|
+
borderRadius: theme2.radius.xs,
|
|
8274
|
+
padding: compact ? "0.25vh 0.6vh" : "0.5vh 0.8vh",
|
|
8275
|
+
cursor: "pointer",
|
|
8276
|
+
display: "flex",
|
|
8277
|
+
alignItems: "center",
|
|
8278
|
+
gap: compact ? "0.3vh" : "0.4vh"
|
|
8279
|
+
},
|
|
8280
|
+
children: [
|
|
8281
|
+
/* @__PURE__ */ jsx(DoorOpen, { size: compact ? "1.1vh" : "1.3vh", color }),
|
|
8282
|
+
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: color, children: label2 ?? locale("PickDoor") })
|
|
8283
|
+
]
|
|
8284
|
+
}
|
|
8285
|
+
)
|
|
8286
|
+
}
|
|
8287
|
+
);
|
|
8288
|
+
}
|
|
8289
|
+
var MapImpl = memo(({
|
|
8290
|
+
children,
|
|
8291
|
+
initialZoom = 2,
|
|
8292
|
+
initialCenter = gameToMap(0, 0),
|
|
8293
|
+
mapStyle = "game"
|
|
8294
|
+
}) => {
|
|
8295
|
+
const mapRef = useRef(null);
|
|
8296
|
+
return /* @__PURE__ */ jsxs(
|
|
8297
|
+
MapContainer,
|
|
8298
|
+
{
|
|
8299
|
+
maxBoundsViscosity: 1,
|
|
8300
|
+
preferCanvas: true,
|
|
8301
|
+
zoom: Math.round(initialZoom),
|
|
8302
|
+
zoomSnap: 1,
|
|
8303
|
+
zoomDelta: 1,
|
|
8304
|
+
zoomControl: false,
|
|
8305
|
+
crs: CRS.Simple,
|
|
8306
|
+
style: {
|
|
8307
|
+
height: "100%",
|
|
8308
|
+
width: "100%",
|
|
8309
|
+
overflow: "hidden",
|
|
8310
|
+
outline: "none !important",
|
|
8311
|
+
border: "none !important",
|
|
8312
|
+
boxShadow: "none !important",
|
|
8313
|
+
backgroundColor: "#384950"
|
|
8314
|
+
},
|
|
8315
|
+
center: initialCenter,
|
|
8316
|
+
attributionControl: false,
|
|
8317
|
+
doubleClickZoom: false,
|
|
8318
|
+
inertia: false,
|
|
8319
|
+
zoomAnimation: false,
|
|
8320
|
+
ref: mapRef,
|
|
8321
|
+
maxBounds: [[-250, -250], [250, 250]],
|
|
8322
|
+
children: [
|
|
8323
|
+
/* @__PURE__ */ jsx(MapLayer, { mapLayer: mapStyle }),
|
|
8324
|
+
children
|
|
8325
|
+
]
|
|
7555
8326
|
}
|
|
7556
8327
|
);
|
|
8328
|
+
});
|
|
8329
|
+
MapImpl.displayName = "DirkMap";
|
|
8330
|
+
var Map2 = MapImpl;
|
|
8331
|
+
var MapLayer = ({ mapLayer }) => {
|
|
8332
|
+
const map = useMap();
|
|
8333
|
+
const layerRef = useRef(null);
|
|
7557
8334
|
useEffect(() => {
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
const inst = getScriptConfigInstance();
|
|
7561
|
-
setScTheme(inst.store.getState()?.theme ?? null);
|
|
7562
|
-
const subscribable = inst.store;
|
|
7563
|
-
if (typeof subscribable.subscribe === "function") {
|
|
7564
|
-
unsubscribe = subscribable.subscribe((s) => {
|
|
7565
|
-
setScTheme(s?.theme ?? null);
|
|
7566
|
-
});
|
|
7567
|
-
}
|
|
7568
|
-
inst.fetchConfig?.().then((full) => {
|
|
7569
|
-
if (full && typeof full === "object") {
|
|
7570
|
-
setScTheme(full.theme ?? null);
|
|
7571
|
-
}
|
|
7572
|
-
}).catch(() => {
|
|
7573
|
-
});
|
|
7574
|
-
} catch {
|
|
8335
|
+
if (layerRef.current) {
|
|
8336
|
+
map.removeLayer(layerRef.current);
|
|
7575
8337
|
}
|
|
8338
|
+
const layer = tileLayer(
|
|
8339
|
+
`https://s.rsg.sc/sc/images/games/GTAV/map/${mapLayer}/{z}/{x}/{y}.jpg`,
|
|
8340
|
+
{
|
|
8341
|
+
maxZoom: 6,
|
|
8342
|
+
minZoom: 4,
|
|
8343
|
+
bounds: latLngBounds(latLng(0, 128), latLng(-192, 0)),
|
|
8344
|
+
tileSize: 256,
|
|
8345
|
+
updateWhenZooming: false,
|
|
8346
|
+
keepBuffer: 2,
|
|
8347
|
+
opacity: 0.75
|
|
8348
|
+
}
|
|
8349
|
+
);
|
|
8350
|
+
layer.addTo(map);
|
|
8351
|
+
layerRef.current = layer;
|
|
7576
8352
|
return () => {
|
|
7577
|
-
|
|
8353
|
+
if (layerRef.current) {
|
|
8354
|
+
map.removeLayer(layerRef.current);
|
|
8355
|
+
}
|
|
7578
8356
|
};
|
|
7579
|
-
}, []);
|
|
7580
|
-
|
|
7581
|
-
|
|
7582
|
-
|
|
7583
|
-
const
|
|
7584
|
-
const
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
7588
|
-
|
|
7589
|
-
|
|
7590
|
-
|
|
8357
|
+
}, [mapLayer, map]);
|
|
8358
|
+
return null;
|
|
8359
|
+
};
|
|
8360
|
+
function ZoomControls() {
|
|
8361
|
+
const theme2 = useMantineTheme();
|
|
8362
|
+
const map = useMap();
|
|
8363
|
+
const buttons = [
|
|
8364
|
+
{ Icon: Plus, fn: () => map.zoomIn() },
|
|
8365
|
+
{ Icon: Minus, fn: () => map.zoomOut() }
|
|
8366
|
+
];
|
|
8367
|
+
return /* @__PURE__ */ jsx(
|
|
8368
|
+
motion.div,
|
|
8369
|
+
{
|
|
8370
|
+
style: {
|
|
8371
|
+
position: "absolute",
|
|
8372
|
+
right: "2vh",
|
|
8373
|
+
top: "2vh",
|
|
8374
|
+
display: "flex",
|
|
8375
|
+
flexDirection: "column",
|
|
8376
|
+
zIndex: 999999,
|
|
8377
|
+
boxShadow: `0 0 1vh ${alpha(theme2.colors.dark[9], 0.85)}`,
|
|
8378
|
+
background: alpha(theme2.colors.dark[9], 0.85),
|
|
8379
|
+
borderRadius: theme2.radius.xs
|
|
8380
|
+
},
|
|
8381
|
+
initial: { opacity: 0, y: -20 },
|
|
8382
|
+
animate: { opacity: 1, y: 0 },
|
|
8383
|
+
exit: { opacity: 0, y: -20 },
|
|
8384
|
+
children: buttons.map(({ Icon, fn }, i) => /* @__PURE__ */ jsx(
|
|
8385
|
+
motion.div,
|
|
8386
|
+
{
|
|
8387
|
+
whileHover: { scale: 1.1, filter: "brightness(1.5)" },
|
|
8388
|
+
onClick: fn,
|
|
8389
|
+
style: {
|
|
8390
|
+
padding: theme2.spacing.xs,
|
|
8391
|
+
cursor: "pointer",
|
|
8392
|
+
display: "flex"
|
|
8393
|
+
},
|
|
8394
|
+
children: /* @__PURE__ */ jsx(Icon, { size: 34, color: theme2.colors.gray[5] })
|
|
8395
|
+
},
|
|
8396
|
+
i
|
|
8397
|
+
))
|
|
8398
|
+
}
|
|
7591
8399
|
);
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
8400
|
+
}
|
|
8401
|
+
var DEFAULT_SPRITE = 162;
|
|
8402
|
+
var DEFAULT_COLOR = 5;
|
|
8403
|
+
function BlipMarker({
|
|
8404
|
+
position,
|
|
8405
|
+
sprite,
|
|
8406
|
+
color,
|
|
8407
|
+
scale = 1,
|
|
8408
|
+
onClick,
|
|
8409
|
+
selected,
|
|
8410
|
+
disabled,
|
|
8411
|
+
fallbackSprite = DEFAULT_SPRITE,
|
|
8412
|
+
fallbackColor = DEFAULT_COLOR
|
|
8413
|
+
}) {
|
|
8414
|
+
const [hovered, setHovered] = useState(false);
|
|
8415
|
+
const mapCoords = useMemo(() => gameToMap(position.x, position.y), [position.x, position.y]);
|
|
8416
|
+
const effectiveSprite = sprite ?? fallbackSprite;
|
|
8417
|
+
const effectiveColor = color ?? fallbackColor;
|
|
8418
|
+
const url = blipUrlForSprite(effectiveSprite);
|
|
8419
|
+
const colorHex = getBlipColor(effectiveColor)?.hex ?? "#ffffff";
|
|
8420
|
+
const handleClick = (e) => {
|
|
8421
|
+
e.originalEvent?.stopPropagation?.();
|
|
8422
|
+
if (disabled) return;
|
|
8423
|
+
onClick?.();
|
|
8424
|
+
};
|
|
8425
|
+
const baseSize = 1.8 * scale;
|
|
8426
|
+
const size = `${baseSize}vh`;
|
|
8427
|
+
const ringSize = `${baseSize * 1.6}vh`;
|
|
8428
|
+
return /* @__PURE__ */ jsx(
|
|
8429
|
+
Marker,
|
|
7597
8430
|
{
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
8431
|
+
position: mapCoords,
|
|
8432
|
+
eventHandlers: onClick ? { click: handleClick } : void 0,
|
|
8433
|
+
icon: /* @__PURE__ */ jsxs(
|
|
8434
|
+
motion.div,
|
|
8435
|
+
{
|
|
8436
|
+
onHoverStart: () => setHovered(true),
|
|
8437
|
+
onHoverEnd: () => setHovered(false),
|
|
8438
|
+
style: {
|
|
8439
|
+
position: "relative",
|
|
8440
|
+
display: "flex",
|
|
8441
|
+
alignItems: "center",
|
|
8442
|
+
justifyContent: "center",
|
|
8443
|
+
cursor: disabled ? "not-allowed" : onClick ? "pointer" : "default",
|
|
8444
|
+
opacity: disabled ? 0.35 : 1,
|
|
8445
|
+
width: size,
|
|
8446
|
+
height: size
|
|
8447
|
+
},
|
|
8448
|
+
animate: { scale: hovered && !disabled ? 1.2 : selected ? 1.15 : 1 },
|
|
8449
|
+
transition: { duration: 0.15, ease: "easeOut" },
|
|
8450
|
+
children: [
|
|
8451
|
+
(selected || hovered) && !disabled && /* @__PURE__ */ jsx(
|
|
8452
|
+
motion.div,
|
|
8453
|
+
{
|
|
8454
|
+
style: {
|
|
8455
|
+
position: "absolute",
|
|
8456
|
+
width: ringSize,
|
|
8457
|
+
height: ringSize,
|
|
8458
|
+
borderRadius: "50%",
|
|
8459
|
+
border: `0.18vh solid ${alpha(colorHex, 0.85)}`,
|
|
8460
|
+
boxShadow: `0 0 1vh ${alpha(colorHex, 0.55)}`
|
|
8461
|
+
},
|
|
8462
|
+
initial: { opacity: 0, scale: 0.8 },
|
|
8463
|
+
animate: { opacity: 1, scale: 1 }
|
|
8464
|
+
}
|
|
8465
|
+
),
|
|
8466
|
+
url && /* @__PURE__ */ jsx(
|
|
8467
|
+
"div",
|
|
8468
|
+
{
|
|
8469
|
+
style: {
|
|
8470
|
+
width: size,
|
|
8471
|
+
height: size,
|
|
8472
|
+
backgroundColor: colorHex,
|
|
8473
|
+
WebkitMaskImage: `url(${url})`,
|
|
8474
|
+
maskImage: `url(${url})`,
|
|
8475
|
+
WebkitMaskRepeat: "no-repeat",
|
|
8476
|
+
maskRepeat: "no-repeat",
|
|
8477
|
+
WebkitMaskPosition: "center",
|
|
8478
|
+
maskPosition: "center",
|
|
8479
|
+
WebkitMaskSize: "contain",
|
|
8480
|
+
maskSize: "contain",
|
|
8481
|
+
filter: [
|
|
8482
|
+
"drop-shadow(0.12vh 0 0 #000)",
|
|
8483
|
+
"drop-shadow(-0.12vh 0 0 #000)",
|
|
8484
|
+
"drop-shadow(0 0.12vh 0 #000)",
|
|
8485
|
+
"drop-shadow(0 -0.12vh 0 #000)",
|
|
8486
|
+
`drop-shadow(0 0 0.4vh ${alpha("#000", 0.7)})`
|
|
8487
|
+
].join(" "),
|
|
8488
|
+
pointerEvents: "none",
|
|
8489
|
+
userSelect: "none"
|
|
8490
|
+
}
|
|
8491
|
+
}
|
|
8492
|
+
)
|
|
8493
|
+
]
|
|
8494
|
+
}
|
|
8495
|
+
)
|
|
7602
8496
|
}
|
|
7603
|
-
)
|
|
7604
|
-
|
|
8497
|
+
);
|
|
8498
|
+
}
|
|
8499
|
+
function useTornEdges() {
|
|
8500
|
+
const game = useSettings((state) => state.game);
|
|
8501
|
+
return game === "rdr3" ? "torn-edge-wrapper" : "";
|
|
8502
|
+
}
|
|
8503
|
+
function TornEdgeSVGFilter() {
|
|
8504
|
+
return /* @__PURE__ */ jsx(
|
|
8505
|
+
"svg",
|
|
8506
|
+
{
|
|
8507
|
+
style: { position: "absolute", width: 0, height: 0, pointerEvents: "none" },
|
|
8508
|
+
"aria-hidden": "true",
|
|
8509
|
+
children: /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("filter", { id: "torn-edge-filter", x: "-50%", y: "-50%", width: "200%", height: "200%", children: [
|
|
8510
|
+
/* @__PURE__ */ jsx(
|
|
8511
|
+
"feTurbulence",
|
|
8512
|
+
{
|
|
8513
|
+
type: "fractalNoise",
|
|
8514
|
+
baseFrequency: "0.018 0.022",
|
|
8515
|
+
numOctaves: "5",
|
|
8516
|
+
seed: "9",
|
|
8517
|
+
result: "noise1"
|
|
8518
|
+
}
|
|
8519
|
+
),
|
|
8520
|
+
/* @__PURE__ */ jsx(
|
|
8521
|
+
"feTurbulence",
|
|
8522
|
+
{
|
|
8523
|
+
type: "fractalNoise",
|
|
8524
|
+
baseFrequency: "0.08 0.12",
|
|
8525
|
+
numOctaves: "2",
|
|
8526
|
+
seed: "3",
|
|
8527
|
+
result: "noise2"
|
|
8528
|
+
}
|
|
8529
|
+
),
|
|
8530
|
+
/* @__PURE__ */ jsx("feBlend", { in: "noise1", in2: "noise2", mode: "multiply", result: "combinedNoise" }),
|
|
8531
|
+
/* @__PURE__ */ jsx(
|
|
8532
|
+
"feDisplacementMap",
|
|
8533
|
+
{
|
|
8534
|
+
in: "SourceGraphic",
|
|
8535
|
+
in2: "combinedNoise",
|
|
8536
|
+
scale: "52",
|
|
8537
|
+
xChannelSelector: "R",
|
|
8538
|
+
yChannelSelector: "G",
|
|
8539
|
+
result: "displaced"
|
|
8540
|
+
}
|
|
8541
|
+
),
|
|
8542
|
+
/* @__PURE__ */ jsx("feGaussianBlur", { stdDeviation: "0.8", in: "displaced", result: "blurred" }),
|
|
8543
|
+
/* @__PURE__ */ jsx("feComponentTransfer", { in: "blurred", result: "alphaFade", children: /* @__PURE__ */ jsx("feFuncA", { type: "gamma", amplitude: "1", exponent: "1.3", offset: "-0.05" }) }),
|
|
8544
|
+
/* @__PURE__ */ jsx("feMorphology", { operator: "erode", radius: "0.4", in: "alphaFade", result: "eroded" }),
|
|
8545
|
+
/* @__PURE__ */ jsx("feMerge", { children: /* @__PURE__ */ jsx("feMergeNode", { in: "eroded" }) })
|
|
8546
|
+
] }) })
|
|
8547
|
+
}
|
|
8548
|
+
);
|
|
8549
|
+
}
|
|
8550
|
+
var moduleCache = /* @__PURE__ */ new Map();
|
|
8551
|
+
function useValidModels(names) {
|
|
8552
|
+
const cacheKey = useMemo(() => {
|
|
8553
|
+
const unique = Array.from(new Set(names.filter((n) => typeof n === "string" && n.length > 0)));
|
|
8554
|
+
unique.sort();
|
|
8555
|
+
return unique.join("|");
|
|
8556
|
+
}, [names]);
|
|
8557
|
+
const [version, setVersion] = useState(0);
|
|
8558
|
+
const inflight = useRef(/* @__PURE__ */ new Set());
|
|
8559
|
+
useEffect(() => {
|
|
8560
|
+
if (!cacheKey) return;
|
|
8561
|
+
const all = cacheKey.split("|").filter(Boolean);
|
|
8562
|
+
const missing = all.filter((n) => !moduleCache.has(n) && !inflight.current.has(n));
|
|
8563
|
+
if (missing.length === 0) return;
|
|
8564
|
+
missing.forEach((n) => inflight.current.add(n));
|
|
8565
|
+
let cancelled = false;
|
|
8566
|
+
fetchNui(
|
|
8567
|
+
"ADMIN_TOOL_QUERY",
|
|
8568
|
+
{ id: "validateModels", value: missing },
|
|
8569
|
+
// Fallback when running outside FiveM (browser dev) — assume valid so the
|
|
8570
|
+
// dev shell doesn't grey out every row.
|
|
8571
|
+
Object.fromEntries(missing.map((n) => [n, true]))
|
|
8572
|
+
).then((result) => {
|
|
8573
|
+
if (cancelled) return;
|
|
8574
|
+
const map = result && typeof result === "object" ? result : {};
|
|
8575
|
+
missing.forEach((n) => {
|
|
8576
|
+
moduleCache.set(n, !!map[n]);
|
|
8577
|
+
inflight.current.delete(n);
|
|
8578
|
+
});
|
|
8579
|
+
setVersion((v) => v + 1);
|
|
8580
|
+
}).catch(() => {
|
|
8581
|
+
if (cancelled) return;
|
|
8582
|
+
missing.forEach((n) => {
|
|
8583
|
+
inflight.current.delete(n);
|
|
8584
|
+
});
|
|
8585
|
+
});
|
|
8586
|
+
return () => {
|
|
8587
|
+
cancelled = true;
|
|
8588
|
+
};
|
|
8589
|
+
}, [cacheKey]);
|
|
8590
|
+
return useMemo(() => {
|
|
8591
|
+
const out = /* @__PURE__ */ new Set();
|
|
8592
|
+
if (!cacheKey) return out;
|
|
8593
|
+
for (const n of cacheKey.split("|")) {
|
|
8594
|
+
if (n && moduleCache.get(n) === true) out.add(n);
|
|
8595
|
+
}
|
|
8596
|
+
return out;
|
|
8597
|
+
}, [cacheKey, version]);
|
|
7605
8598
|
}
|
|
7606
8599
|
var Vector2Schema = z.object({
|
|
7607
8600
|
x: z.number(),
|
|
@@ -7619,6 +8612,6 @@ var Vector4Schema = z.object({
|
|
|
7619
8612
|
w: z.number()
|
|
7620
8613
|
});
|
|
7621
8614
|
|
|
7622
|
-
export { AccountSelect, AdminPageTitle, AnimPostFxSelect, AsyncSaveButton, BlipColorSelect, BlipDisplaySelect, BlipIconSelect, BorderedIcon, ConfigPanel, ConfirmModal, ControlMultiSelect, ControlSelect, Counter, DirkProvider, DiscordRoleSelect, FiveMKeyBindInput, FloatingParticles, FormProvider, GTA_CONTROLS, GTA_CONTROL_GROUP_ORDER, GroupName, GroupRank, GroupSelect, INPUT_MAPPER_KEYS_BY_PRIMARY, INPUT_MAPPER_PRIMARY_OPTIONS, InfoBox, InputContainer, LevelBanner, LevelPanel, MissingItemsBanner, Modal, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PositionPicker, PromptModal, ScenarioSelect, SegmentedControl, SegmentedProgress, SelectItem, SwitchPanel, TestBed, ThemeOverrideSection, Title, TornEdgeSVGFilter, Vector2Schema, Vector3Schema, Vector4DeleteButton, Vector4Display, Vector4Schema, WorldPositionGotoButton, WorldPositionSetButton, colorWithAlpha, copyToClipboard, createFormStore, createScriptConfig, createSkill, extractDefaults, fetchLuaTable, fetchNui, formatGtaControl, gameToMap, getGtaControl, getImageShape, getItemImageUrl, getScriptConfigInstance, initialFetches, internalEvent, isEnvBrowser, isProfanity, latPr100, locale, localeStore, mapCenter, mapToGame, noop, numberToRoman, openLink, registerInitialFetch, registerInitialLuaTableFetch, runFetches, selectAllGroups, splitFAString, updatePresignedURL, uploadImage, useAudio, useAutoFetcher, useForm, useFormActions, useFormError, useFormErrors, useFormField, useFormFields, useFrameworkGroups, useItems, useItemsList, useMissingItemsAudit, useModal, useModalActions, useNavigation, useNavigationStore, useNuiEvent, useProfanityStore, useSettings, useTornEdges };
|
|
8615
|
+
export { AccountSelect, AdminPageTitle, AnimPostFxSelect, AsyncSaveButton, BlipColorSelect, BlipDisplaySelect, BlipIconSelect, BlipMarker, BorderedIcon, ConfigPanel, ConfirmModal, ControlMultiSelect, ControlSelect, Counter, DirkProvider, DiscordRoleSelect, DoorPickerButton, FiveMKeyBindInput, FloatingParticles, FormProvider, GTA_CONTROLS, GTA_CONTROL_GROUP_ORDER, GroupName, GroupRank, GroupSelect, INPUT_MAPPER_KEYS_BY_PRIMARY, INPUT_MAPPER_PRIMARY_OPTIONS, InfoBox, InputContainer, InstructionPanel, LevelBanner, LevelPanel, Map2 as Map, MapLayer, MissingItemsBanner, Modal, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PlayerSelect, PositionPicker, PromptModal, ScenarioSelect, SegmentedControl, SegmentedProgress, SelectItem, SwitchPanel, TestBed, ThemeOverrideSection, Title, TornEdgeSVGFilter, Vector2Schema, Vector3Schema, Vector4DeleteButton, Vector4Display, Vector4Schema, WorldPositionGotoButton, WorldPositionPicker, WorldPositionSetButton, ZoomControls, blipUrl, blipUrlForSprite, clearAdminState, colorWithAlpha, copyToClipboard, createFormStore, createScriptConfig, createSkill, dirkQueryClient, ensureFrameworkGroups, extractDefaults, fetchLuaTable, fetchNui, formatGtaControl, gameToMap, getBlipColor, getBlipEntry, getGtaControl, getImageShape, getItemImageUrl, getScriptConfigInstance, initialFetches, internalEvent, isEnvBrowser, isProfanity, latPr100, locale, localeStore, mapCenter, mapToGame, noop, numberToRoman, openLink, registerInitialFetch, registerInitialLuaTableFetch, runFetches, selectAllGroups, splitFAString, updatePresignedURL, uploadImage, useAdminState, useAdminToolStore, useAudio, useAutoFetcher, useForm, useFormActions, useFormError, useFormErrors, useFormField, useFormFields, useFrameworkGroups, useItems, useItemsList, useMissingItemsAudit, useModal, useModalActions, useNavigation, useNavigationStore, useNuiEvent, usePickDoor, usePlayers, useProfanityStore, useSettings, useTornEdges, useValidModels };
|
|
7623
8616
|
//# sourceMappingURL=index.js.map
|
|
7624
8617
|
//# sourceMappingURL=index.js.map
|