dirk-cfx-react 1.1.70 → 1.1.72
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 +468 -36
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.cts +49 -1
- package/dist/components/index.d.ts +49 -1
- package/dist/components/index.js +465 -39
- package/dist/components/index.js.map +1 -1
- package/dist/index.cjs +468 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +465 -39
- package/dist/index.js.map +1 -1
- package/package.json +113 -113
package/dist/components/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { Flex, Text, Image, TextInput, Select, Box, useMantineTheme, Tooltip, alpha, Progress, RingProgress, Portal, Button, NumberInput, MultiSelect, Loader, ActionIcon, Stack, Group, JsonInput } from '@mantine/core';
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
-
import { createContext, useContext, useRef, useState, useEffect, useMemo } from 'react';
|
|
3
|
+
import { createContext, useContext, useRef, useState, useEffect, useCallback, useMemo } from 'react';
|
|
4
4
|
import { create, useStore, createStore } from 'zustand';
|
|
5
5
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
6
6
|
import { motion, AnimatePresence, useMotionValue } from 'framer-motion';
|
|
7
|
-
import { Info, X, AlertTriangle, Trash2, MapPin, Crosshair, EyeOff, Eye, RotateCcw,
|
|
7
|
+
import { Info, X, AlertTriangle, Trash2, RefreshCw, ChevronDown, Check, Copy, MapPin, Crosshair, EyeOff, Eye, RotateCcw, FlaskConical, ChevronUp, ArrowLeft, Undo2, Redo2, Save, History, XCircle, Code2, Search, Filter, User } from 'lucide-react';
|
|
8
8
|
import clickSoundUrl from '../click_sound-PNCRRTM4.mp3';
|
|
9
9
|
import hoverSoundUrl from '../hover_sound-NBUA222C.mp3';
|
|
10
|
+
import { notifications } from '@mantine/notifications';
|
|
10
11
|
import { QueryClient, QueryClientProvider, useInfiniteQuery } from '@tanstack/react-query';
|
|
11
12
|
|
|
12
13
|
// src/components/BlipSelect.tsx
|
|
@@ -1228,11 +1229,11 @@ var colorNames = {
|
|
|
1228
1229
|
Yellow: { r: 255, g: 255, b: 0 },
|
|
1229
1230
|
YellowGreen: { r: 154, g: 205, b: 50 }
|
|
1230
1231
|
};
|
|
1231
|
-
function colorWithAlpha(color,
|
|
1232
|
+
function colorWithAlpha(color, alpha10) {
|
|
1232
1233
|
const lowerCasedColor = color.toLowerCase();
|
|
1233
1234
|
if (colorNames[lowerCasedColor]) {
|
|
1234
1235
|
const rgb = colorNames[lowerCasedColor];
|
|
1235
|
-
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${
|
|
1236
|
+
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha10})`;
|
|
1236
1237
|
}
|
|
1237
1238
|
if (/^#([A-Fa-f0-9]{6})$/.test(color)) {
|
|
1238
1239
|
const hex = color.slice(1);
|
|
@@ -1240,12 +1241,12 @@ function colorWithAlpha(color, alpha9) {
|
|
|
1240
1241
|
const r = bigint >> 16 & 255;
|
|
1241
1242
|
const g = bigint >> 8 & 255;
|
|
1242
1243
|
const b = bigint & 255;
|
|
1243
|
-
return `rgba(${r}, ${g}, ${b}, ${
|
|
1244
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha10})`;
|
|
1244
1245
|
}
|
|
1245
1246
|
if (/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/.test(color)) {
|
|
1246
1247
|
const result = color.match(/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/);
|
|
1247
1248
|
if (result) {
|
|
1248
|
-
return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${
|
|
1249
|
+
return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${alpha10})`;
|
|
1249
1250
|
}
|
|
1250
1251
|
}
|
|
1251
1252
|
return color;
|
|
@@ -3197,6 +3198,246 @@ function ConfirmModal({
|
|
|
3197
3198
|
}
|
|
3198
3199
|
) });
|
|
3199
3200
|
}
|
|
3201
|
+
var TABS = [
|
|
3202
|
+
{ id: "ox", label: "ox_inventory" },
|
|
3203
|
+
{ id: "qb", label: "qb-inventory" },
|
|
3204
|
+
{ id: "esx", label: "ESX legacy SQL" }
|
|
3205
|
+
];
|
|
3206
|
+
var useMissingItemsAudit = create((set, get) => ({
|
|
3207
|
+
data: null,
|
|
3208
|
+
loaded: false,
|
|
3209
|
+
inFlight: false,
|
|
3210
|
+
refresh: async () => {
|
|
3211
|
+
if (get().inFlight) return;
|
|
3212
|
+
set({ inFlight: true });
|
|
3213
|
+
try {
|
|
3214
|
+
const res = await fetchNui("GET_MISSING_ITEMS", void 0, {
|
|
3215
|
+
success: true,
|
|
3216
|
+
data: { missing: [], snippets: { ox: "", qb: "", esx: "" } }
|
|
3217
|
+
});
|
|
3218
|
+
if (res?.success && res.data) {
|
|
3219
|
+
set({ data: res.data, loaded: true });
|
|
3220
|
+
} else {
|
|
3221
|
+
set({ loaded: true });
|
|
3222
|
+
}
|
|
3223
|
+
} catch {
|
|
3224
|
+
set({ loaded: true });
|
|
3225
|
+
} finally {
|
|
3226
|
+
set({ inFlight: false });
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
}));
|
|
3230
|
+
function MissingItemsBanner() {
|
|
3231
|
+
const theme = useMantineTheme();
|
|
3232
|
+
const audit = useMissingItemsAudit((s) => s.data);
|
|
3233
|
+
const loaded = useMissingItemsAudit((s) => s.loaded);
|
|
3234
|
+
const inFlight = useMissingItemsAudit((s) => s.inFlight);
|
|
3235
|
+
const refresh = useMissingItemsAudit((s) => s.refresh);
|
|
3236
|
+
const [expanded, setExpanded] = useState(false);
|
|
3237
|
+
const [activeTab, setActiveTab] = useState("ox");
|
|
3238
|
+
const [hoveredTab, setHoveredTab] = useState(null);
|
|
3239
|
+
const [copied, setCopied] = useState(null);
|
|
3240
|
+
useEffect(() => {
|
|
3241
|
+
if (!loaded) refresh();
|
|
3242
|
+
}, [loaded, refresh]);
|
|
3243
|
+
const handleCopy = useCallback((tab) => {
|
|
3244
|
+
if (!audit) return;
|
|
3245
|
+
const text = audit.snippets[tab] ?? "";
|
|
3246
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
3247
|
+
setCopied(tab);
|
|
3248
|
+
setTimeout(() => setCopied((c) => c === tab ? null : c), 1500);
|
|
3249
|
+
}).catch(() => {
|
|
3250
|
+
});
|
|
3251
|
+
}, [audit]);
|
|
3252
|
+
const handleRefresh = useCallback((e) => {
|
|
3253
|
+
e.stopPropagation();
|
|
3254
|
+
refresh();
|
|
3255
|
+
}, [refresh]);
|
|
3256
|
+
if (!audit || audit.missing.length === 0) return null;
|
|
3257
|
+
const warnColor = "#f59e0b";
|
|
3258
|
+
const names = audit.missing.map((m) => m.name);
|
|
3259
|
+
return /* @__PURE__ */ jsxs(
|
|
3260
|
+
"div",
|
|
3261
|
+
{
|
|
3262
|
+
style: {
|
|
3263
|
+
background: alpha(warnColor, 0.06),
|
|
3264
|
+
border: `0.1vh solid ${alpha(warnColor, 0.35)}`,
|
|
3265
|
+
borderLeft: `0.3vh solid ${warnColor}`,
|
|
3266
|
+
borderRadius: theme.radius.xs,
|
|
3267
|
+
margin: "0.6vh 1vh",
|
|
3268
|
+
overflow: "hidden"
|
|
3269
|
+
},
|
|
3270
|
+
children: [
|
|
3271
|
+
/* @__PURE__ */ jsxs(Flex, { align: "center", gap: "0.8vh", p: "0.8vh 1vh", style: { cursor: "pointer" }, onClick: () => setExpanded((e) => !e), children: [
|
|
3272
|
+
/* @__PURE__ */ jsx(AlertTriangle, { size: "1.8vh", color: warnColor, strokeWidth: 2.5 }),
|
|
3273
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", style: { flex: 1, minWidth: 0 }, children: [
|
|
3274
|
+
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.07em", c: warnColor, children: audit.missing.length === 1 ? "1 item missing from your inventory" : `${audit.missing.length} items missing from your inventory` }),
|
|
3275
|
+
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.5)", lineClamp: 1, style: { fontFamily: "monospace" }, children: names.join(", ") })
|
|
3276
|
+
] }),
|
|
3277
|
+
/* @__PURE__ */ jsx(
|
|
3278
|
+
"button",
|
|
3279
|
+
{
|
|
3280
|
+
onClick: handleRefresh,
|
|
3281
|
+
disabled: inFlight,
|
|
3282
|
+
style: {
|
|
3283
|
+
background: "transparent",
|
|
3284
|
+
border: "none",
|
|
3285
|
+
padding: "0.3vh",
|
|
3286
|
+
cursor: inFlight ? "wait" : "pointer",
|
|
3287
|
+
display: "flex",
|
|
3288
|
+
alignItems: "center",
|
|
3289
|
+
justifyContent: "center",
|
|
3290
|
+
opacity: inFlight ? 0.4 : 0.7
|
|
3291
|
+
},
|
|
3292
|
+
title: "Re-check",
|
|
3293
|
+
children: /* @__PURE__ */ jsx(
|
|
3294
|
+
motion.span,
|
|
3295
|
+
{
|
|
3296
|
+
animate: { rotate: inFlight ? 360 : 0 },
|
|
3297
|
+
transition: inFlight ? { duration: 1, repeat: Infinity, ease: "linear" } : { duration: 0 },
|
|
3298
|
+
style: { display: "flex", alignItems: "center", justifyContent: "center" },
|
|
3299
|
+
children: /* @__PURE__ */ jsx(RefreshCw, { size: "1.5vh", color: alpha(warnColor, 0.7) })
|
|
3300
|
+
}
|
|
3301
|
+
)
|
|
3302
|
+
}
|
|
3303
|
+
),
|
|
3304
|
+
/* @__PURE__ */ jsx(
|
|
3305
|
+
motion.div,
|
|
3306
|
+
{
|
|
3307
|
+
animate: { rotate: expanded ? 180 : 0 },
|
|
3308
|
+
transition: { duration: 0.18 },
|
|
3309
|
+
style: { display: "flex", alignItems: "center", justifyContent: "center" },
|
|
3310
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { size: "1.8vh", color: alpha(warnColor, 0.7) })
|
|
3311
|
+
}
|
|
3312
|
+
)
|
|
3313
|
+
] }),
|
|
3314
|
+
/* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: expanded && /* @__PURE__ */ jsxs(
|
|
3315
|
+
motion.div,
|
|
3316
|
+
{
|
|
3317
|
+
initial: { height: 0, opacity: 0 },
|
|
3318
|
+
animate: { height: "auto", opacity: 1 },
|
|
3319
|
+
exit: { height: 0, opacity: 0 },
|
|
3320
|
+
transition: { duration: 0.18, ease: "easeOut" },
|
|
3321
|
+
style: { overflow: "hidden", borderTop: `0.1vh solid ${alpha(warnColor, 0.18)}` },
|
|
3322
|
+
children: [
|
|
3323
|
+
/* @__PURE__ */ jsx(Flex, { gap: "0", style: { borderBottom: `0.1vh solid ${alpha(warnColor, 0.18)}` }, children: TABS.map((tab) => {
|
|
3324
|
+
const active = tab.id === activeTab;
|
|
3325
|
+
const hovered = hoveredTab === tab.id;
|
|
3326
|
+
let bg = "transparent";
|
|
3327
|
+
if (active) bg = alpha(warnColor, 0.12);
|
|
3328
|
+
else if (hovered) bg = alpha(warnColor, 0.08);
|
|
3329
|
+
return /* @__PURE__ */ jsx(
|
|
3330
|
+
"button",
|
|
3331
|
+
{
|
|
3332
|
+
onClick: (e) => {
|
|
3333
|
+
e.stopPropagation();
|
|
3334
|
+
setActiveTab(tab.id);
|
|
3335
|
+
},
|
|
3336
|
+
onMouseEnter: () => setHoveredTab(tab.id),
|
|
3337
|
+
onMouseLeave: () => setHoveredTab((h) => h === tab.id ? null : h),
|
|
3338
|
+
style: {
|
|
3339
|
+
flex: 1,
|
|
3340
|
+
background: bg,
|
|
3341
|
+
border: "none",
|
|
3342
|
+
borderBottom: active ? `0.2vh solid ${warnColor}` : "0.2vh solid transparent",
|
|
3343
|
+
padding: "0.3vh 1vh",
|
|
3344
|
+
cursor: active ? "default" : "pointer",
|
|
3345
|
+
color: active ? warnColor : "rgba(255,255,255,0.5)",
|
|
3346
|
+
fontFamily: "Akrobat Bold",
|
|
3347
|
+
fontSize: "var(--mantine-font-size-xxs)",
|
|
3348
|
+
letterSpacing: "0.07em",
|
|
3349
|
+
textTransform: "uppercase",
|
|
3350
|
+
transition: "background 0.12s"
|
|
3351
|
+
},
|
|
3352
|
+
children: tab.label
|
|
3353
|
+
},
|
|
3354
|
+
tab.id
|
|
3355
|
+
);
|
|
3356
|
+
}) }),
|
|
3357
|
+
/* @__PURE__ */ jsx(
|
|
3358
|
+
CodeView,
|
|
3359
|
+
{
|
|
3360
|
+
code: audit.snippets[activeTab] ?? "",
|
|
3361
|
+
copied: copied === activeTab,
|
|
3362
|
+
onCopy: (e) => {
|
|
3363
|
+
e.stopPropagation();
|
|
3364
|
+
handleCopy(activeTab);
|
|
3365
|
+
},
|
|
3366
|
+
warnColor
|
|
3367
|
+
}
|
|
3368
|
+
)
|
|
3369
|
+
]
|
|
3370
|
+
},
|
|
3371
|
+
"expanded"
|
|
3372
|
+
) })
|
|
3373
|
+
]
|
|
3374
|
+
}
|
|
3375
|
+
);
|
|
3376
|
+
}
|
|
3377
|
+
function CodeView({
|
|
3378
|
+
code,
|
|
3379
|
+
copied,
|
|
3380
|
+
onCopy,
|
|
3381
|
+
warnColor
|
|
3382
|
+
}) {
|
|
3383
|
+
const theme = useMantineTheme();
|
|
3384
|
+
const [hovered, setHovered] = useState(false);
|
|
3385
|
+
const lines = code === "" ? [""] : code.split("\n");
|
|
3386
|
+
const lineNumWidth = String(lines.length).length;
|
|
3387
|
+
const copyBg = copied ? alpha("#22c55e", 0.15) : hovered ? alpha(warnColor, 0.18) : alpha(warnColor, 0.1);
|
|
3388
|
+
return /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
3389
|
+
/* @__PURE__ */ jsxs(
|
|
3390
|
+
"button",
|
|
3391
|
+
{
|
|
3392
|
+
onClick: onCopy,
|
|
3393
|
+
onMouseEnter: () => setHovered(true),
|
|
3394
|
+
onMouseLeave: () => setHovered(false),
|
|
3395
|
+
style: {
|
|
3396
|
+
position: "absolute",
|
|
3397
|
+
top: "0.6vh",
|
|
3398
|
+
right: "0.8vh",
|
|
3399
|
+
zIndex: 2,
|
|
3400
|
+
background: copyBg,
|
|
3401
|
+
border: `0.1vh solid ${alpha(copied ? "#22c55e" : warnColor, 0.35)}`,
|
|
3402
|
+
borderRadius: theme.radius.xs,
|
|
3403
|
+
padding: "0.4vh 0.7vh",
|
|
3404
|
+
cursor: "pointer",
|
|
3405
|
+
display: "flex",
|
|
3406
|
+
alignItems: "center",
|
|
3407
|
+
gap: "0.4vh",
|
|
3408
|
+
transition: "background 0.12s"
|
|
3409
|
+
},
|
|
3410
|
+
children: [
|
|
3411
|
+
copied ? /* @__PURE__ */ jsx(Check, { size: "1.4vh", color: "#22c55e" }) : /* @__PURE__ */ jsx(Copy, { size: "1.4vh", color: warnColor }),
|
|
3412
|
+
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: copied ? "#22c55e" : warnColor, children: copied ? "Copied" : "Copy" })
|
|
3413
|
+
]
|
|
3414
|
+
}
|
|
3415
|
+
),
|
|
3416
|
+
/* @__PURE__ */ jsx("div", { style: {
|
|
3417
|
+
background: alpha(theme.colors.dark[9], 0.6),
|
|
3418
|
+
maxHeight: "40vh",
|
|
3419
|
+
overflowY: "auto",
|
|
3420
|
+
overflowX: "auto",
|
|
3421
|
+
padding: "0.6vh 0"
|
|
3422
|
+
}, children: /* @__PURE__ */ jsx("table", { style: { borderCollapse: "collapse", width: "100%", fontFamily: "monospace", fontSize: "1.2vh", lineHeight: 1.5 }, children: /* @__PURE__ */ jsx("tbody", { children: lines.map((line, i) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
3423
|
+
/* @__PURE__ */ jsx("td", { style: {
|
|
3424
|
+
width: `${lineNumWidth + 2}ch`,
|
|
3425
|
+
textAlign: "right",
|
|
3426
|
+
padding: "0 0.8vh 0 1vh",
|
|
3427
|
+
color: "rgba(255,255,255,0.25)",
|
|
3428
|
+
userSelect: "none",
|
|
3429
|
+
whiteSpace: "nowrap",
|
|
3430
|
+
verticalAlign: "top"
|
|
3431
|
+
}, children: i + 1 }),
|
|
3432
|
+
/* @__PURE__ */ jsx("td", { style: {
|
|
3433
|
+
padding: "0 1vh",
|
|
3434
|
+
color: "rgba(255,255,255,0.85)",
|
|
3435
|
+
whiteSpace: "pre",
|
|
3436
|
+
verticalAlign: "top"
|
|
3437
|
+
}, children: line || "\u200B" })
|
|
3438
|
+
] }, i)) }) }) })
|
|
3439
|
+
] });
|
|
3440
|
+
}
|
|
3200
3441
|
function getNested(obj, path) {
|
|
3201
3442
|
return path.split(".").reduce((acc, key) => acc ? acc[key] : void 0, obj);
|
|
3202
3443
|
}
|
|
@@ -3799,7 +4040,8 @@ function ConfigPanelInner({
|
|
|
3799
4040
|
resetConfirmText,
|
|
3800
4041
|
defaultConfig,
|
|
3801
4042
|
width,
|
|
3802
|
-
height
|
|
4043
|
+
height,
|
|
4044
|
+
suppressMissingItemsBanner
|
|
3803
4045
|
}) {
|
|
3804
4046
|
const { updateConfig, resetConfig, getHistory } = getScriptConfigInstance();
|
|
3805
4047
|
const form = useForm();
|
|
@@ -4022,18 +4264,21 @@ function ConfigPanelInner({
|
|
|
4022
4264
|
] })
|
|
4023
4265
|
] })
|
|
4024
4266
|
] }),
|
|
4025
|
-
/* @__PURE__ */
|
|
4026
|
-
|
|
4027
|
-
{
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4267
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: [
|
|
4268
|
+
!suppressMissingItemsBanner && /* @__PURE__ */ jsx(MissingItemsBanner, {}),
|
|
4269
|
+
/* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
|
|
4270
|
+
motion.div,
|
|
4271
|
+
{
|
|
4272
|
+
initial: firstMountRef.current ? (firstMountRef.current = false, false) : { opacity: 0, y: 4 },
|
|
4273
|
+
animate: { opacity: 1, y: 0 },
|
|
4274
|
+
exit: { opacity: 0, y: -4 },
|
|
4275
|
+
transition: { duration: 0.15 },
|
|
4276
|
+
style: { flex: 1, display: "flex", flexDirection: "column", overflowY: "auto" },
|
|
4277
|
+
children: children(activeTab)
|
|
4278
|
+
},
|
|
4279
|
+
activeTab
|
|
4280
|
+
) })
|
|
4281
|
+
] })
|
|
4037
4282
|
]
|
|
4038
4283
|
}
|
|
4039
4284
|
)
|
|
@@ -4075,12 +4320,26 @@ function ConfigPanel(props) {
|
|
|
4075
4320
|
if (result?.success) {
|
|
4076
4321
|
form.reinitialize(cloneConfig(form.values));
|
|
4077
4322
|
configPanelQueryClient.invalidateQueries({ queryKey: ["scriptConfigHistory"] });
|
|
4323
|
+
useMissingItemsAudit.getState().refresh();
|
|
4324
|
+
notifications.show({
|
|
4325
|
+
color: "green",
|
|
4326
|
+
title: locale("ConfigSaveSuccessTitle"),
|
|
4327
|
+
message: locale("ConfigSaveSuccessBody"),
|
|
4328
|
+
autoClose: 3e3
|
|
4329
|
+
});
|
|
4078
4330
|
return;
|
|
4079
4331
|
}
|
|
4080
4332
|
form.reinitialize(cloneConfig(store.getState()));
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4333
|
+
const err = result?._error || "Unknown";
|
|
4334
|
+
console.warn(`[ConfigPanel] config save failed: ${err}`);
|
|
4335
|
+
const titleKey = err === "NoPermission" ? "ConfigSaveNoPermissionTitle" : err === "VersionConflict" ? "ConfigSaveVersionConflictTitle" : err === "NotReady" ? "ConfigSaveNotReadyTitle" : "ConfigSaveFailedTitle";
|
|
4336
|
+
const bodyKey = err === "NoPermission" ? "ConfigSaveNoPermissionBody" : err === "VersionConflict" ? "ConfigSaveVersionConflictBody" : err === "NotReady" ? "ConfigSaveNotReadyBody" : "ConfigSaveFailedBody";
|
|
4337
|
+
notifications.show({
|
|
4338
|
+
color: "red",
|
|
4339
|
+
title: locale(titleKey),
|
|
4340
|
+
message: locale(bodyKey, err),
|
|
4341
|
+
autoClose: 6e3
|
|
4342
|
+
});
|
|
4084
4343
|
} finally {
|
|
4085
4344
|
setIsSaving(false);
|
|
4086
4345
|
}
|
|
@@ -4099,6 +4358,7 @@ function ConfigPanel(props) {
|
|
|
4099
4358
|
}
|
|
4100
4359
|
) });
|
|
4101
4360
|
}
|
|
4361
|
+
var MISSING_COLOR = "#f59e0b";
|
|
4102
4362
|
function LazyImage({ src, style }) {
|
|
4103
4363
|
const [visible, setVisible] = useState(false);
|
|
4104
4364
|
const ref = useRef(null);
|
|
@@ -4116,14 +4376,19 @@ function LazyImage({ src, style }) {
|
|
|
4116
4376
|
}
|
|
4117
4377
|
function SelectItem(props) {
|
|
4118
4378
|
const invItems = useItems();
|
|
4379
|
+
const isMissing = !!props.value && !invItems[props.value];
|
|
4119
4380
|
const formattedItems = useMemo(() => {
|
|
4120
4381
|
const seen = /* @__PURE__ */ new Set();
|
|
4121
|
-
|
|
4382
|
+
const list = useItemsList(props.excludeItemNames ?? []).filter((item) => {
|
|
4122
4383
|
if (seen.has(item.name)) return false;
|
|
4123
4384
|
seen.add(item.name);
|
|
4124
4385
|
return true;
|
|
4125
4386
|
}).map((item) => ({ value: item.name, label: item.label, image: item.image }));
|
|
4126
|
-
|
|
4387
|
+
if (isMissing) {
|
|
4388
|
+
list.unshift({ value: props.value, label: props.value, image: "" });
|
|
4389
|
+
}
|
|
4390
|
+
return list;
|
|
4391
|
+
}, [invItems, props.excludeItemNames, props.value, isMissing]);
|
|
4127
4392
|
return /* @__PURE__ */ jsx(
|
|
4128
4393
|
Select,
|
|
4129
4394
|
{
|
|
@@ -4138,10 +4403,11 @@ function SelectItem(props) {
|
|
|
4138
4403
|
data: formattedItems,
|
|
4139
4404
|
allowDeselect: false,
|
|
4140
4405
|
searchable: true,
|
|
4406
|
+
styles: isMissing ? { input: { color: MISSING_COLOR } } : void 0,
|
|
4141
4407
|
comboboxProps: { withinPortal: true, zIndex: 2e3 },
|
|
4142
4408
|
leftSectionWidth: "4vh",
|
|
4143
4409
|
leftSectionPointerEvents: "none",
|
|
4144
|
-
leftSection: props.value ? /* @__PURE__ */ jsx(
|
|
4410
|
+
leftSection: isMissing ? /* @__PURE__ */ jsx(Flex, { align: "center", justify: "center", w: "4vh", h: "4vh", children: /* @__PURE__ */ jsx(AlertTriangle, { size: "2vh", color: MISSING_COLOR, strokeWidth: 2.5 }) }) : props.value ? /* @__PURE__ */ jsx(
|
|
4145
4411
|
Image,
|
|
4146
4412
|
{
|
|
4147
4413
|
fallbackSrc: "/placeholder.png",
|
|
@@ -4152,19 +4418,37 @@ function SelectItem(props) {
|
|
|
4152
4418
|
}
|
|
4153
4419
|
) : null,
|
|
4154
4420
|
nothingFoundMessage: locale("NoItemsFound"),
|
|
4155
|
-
renderOption: (item) =>
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
{
|
|
4159
|
-
|
|
4160
|
-
style: {
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4421
|
+
renderOption: (item) => {
|
|
4422
|
+
const optionMissing = !invItems[item.option.value] && item.option.value === props.value;
|
|
4423
|
+
if (optionMissing) {
|
|
4424
|
+
return /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "xs", w: "100%", children: [
|
|
4425
|
+
/* @__PURE__ */ jsx(Flex, { align: "center", justify: "center", w: "4vh", h: "4vh", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx(AlertTriangle, { size: "2vh", color: MISSING_COLOR, strokeWidth: 2.5 }) }),
|
|
4426
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", style: { flex: 1, minWidth: 0 }, children: [
|
|
4427
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: MISSING_COLOR, style: { fontFamily: "monospace" }, children: item.option.value }),
|
|
4428
|
+
/* @__PURE__ */ jsx(Text, { size: "xxs", c: "dimmed", children: locale("ItemNotInInventory") })
|
|
4429
|
+
] }),
|
|
4430
|
+
/* @__PURE__ */ jsx("div", { style: {
|
|
4431
|
+
background: "rgba(245,158,11,0.12)",
|
|
4432
|
+
border: `0.1vh solid ${MISSING_COLOR}59`,
|
|
4433
|
+
borderRadius: "0.3vh",
|
|
4434
|
+
padding: "0.1vh 0.6vh"
|
|
4435
|
+
}, children: /* @__PURE__ */ jsx(Text, { size: "xxs", c: MISSING_COLOR, ff: "Akrobat Bold", tt: "uppercase", lts: "0.06em", children: locale("Missing") }) })
|
|
4436
|
+
] });
|
|
4437
|
+
}
|
|
4438
|
+
return /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "xs", w: "100%", children: [
|
|
4439
|
+
/* @__PURE__ */ jsx(
|
|
4440
|
+
LazyImage,
|
|
4441
|
+
{
|
|
4442
|
+
src: invItems[item.option.value]?.image || "",
|
|
4443
|
+
style: { aspectRatio: "1 / 1" }
|
|
4444
|
+
}
|
|
4445
|
+
),
|
|
4446
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", children: [
|
|
4447
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", children: item.option.label }),
|
|
4448
|
+
/* @__PURE__ */ jsx(Text, { size: "xxs", c: "dimmed", children: item.option.value })
|
|
4449
|
+
] })
|
|
4450
|
+
] });
|
|
4451
|
+
}
|
|
4168
4452
|
}
|
|
4169
4453
|
);
|
|
4170
4454
|
}
|
|
@@ -4381,6 +4665,148 @@ function PickerButton({
|
|
|
4381
4665
|
}
|
|
4382
4666
|
) });
|
|
4383
4667
|
}
|
|
4668
|
+
function fmtV4(n) {
|
|
4669
|
+
return Number.isFinite(n) ? n.toFixed(2) : "0.00";
|
|
4670
|
+
}
|
|
4671
|
+
function Vector4Display({ value }) {
|
|
4672
|
+
const theme = useMantineTheme();
|
|
4673
|
+
return /* @__PURE__ */ jsx(
|
|
4674
|
+
Flex,
|
|
4675
|
+
{
|
|
4676
|
+
align: "center",
|
|
4677
|
+
gap: "xs",
|
|
4678
|
+
p: "xs",
|
|
4679
|
+
style: {
|
|
4680
|
+
background: alpha(theme.colors.dark[5], 0.35),
|
|
4681
|
+
border: "0.1vh solid rgba(255,255,255,0.05)",
|
|
4682
|
+
borderRadius: theme.radius.xs
|
|
4683
|
+
},
|
|
4684
|
+
children: /* @__PURE__ */ jsxs(
|
|
4685
|
+
Text,
|
|
4686
|
+
{
|
|
4687
|
+
ff: "monospace",
|
|
4688
|
+
size: "xxs",
|
|
4689
|
+
c: "rgba(255,255,255,0.85)",
|
|
4690
|
+
style: { flex: 1, letterSpacing: "0.02em", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" },
|
|
4691
|
+
children: [
|
|
4692
|
+
"vector4(",
|
|
4693
|
+
fmtV4(value.x),
|
|
4694
|
+
", ",
|
|
4695
|
+
fmtV4(value.y),
|
|
4696
|
+
", ",
|
|
4697
|
+
fmtV4(value.z),
|
|
4698
|
+
", ",
|
|
4699
|
+
fmtV4(value.w),
|
|
4700
|
+
")"
|
|
4701
|
+
]
|
|
4702
|
+
}
|
|
4703
|
+
)
|
|
4704
|
+
}
|
|
4705
|
+
);
|
|
4706
|
+
}
|
|
4707
|
+
function Vector4ActionButton({
|
|
4708
|
+
icon,
|
|
4709
|
+
label,
|
|
4710
|
+
tooltip,
|
|
4711
|
+
onClick,
|
|
4712
|
+
color,
|
|
4713
|
+
compact
|
|
4714
|
+
}) {
|
|
4715
|
+
const theme = useMantineTheme();
|
|
4716
|
+
return /* @__PURE__ */ jsx(Tooltip, { label: tooltip, position: "top", withArrow: true, withinPortal: true, zIndex: 2e3, children: /* @__PURE__ */ jsxs(
|
|
4717
|
+
motion.button,
|
|
4718
|
+
{
|
|
4719
|
+
onClick,
|
|
4720
|
+
whileHover: { background: alpha(color, 0.18) },
|
|
4721
|
+
whileTap: { scale: 0.95 },
|
|
4722
|
+
style: {
|
|
4723
|
+
background: alpha(color, 0.1),
|
|
4724
|
+
border: `0.1vh solid ${alpha(color, 0.35)}`,
|
|
4725
|
+
borderRadius: theme.radius.xs,
|
|
4726
|
+
padding: compact ? "0.25vh 0.6vh" : "0.5vh 0.8vh",
|
|
4727
|
+
cursor: "pointer",
|
|
4728
|
+
display: "flex",
|
|
4729
|
+
alignItems: "center",
|
|
4730
|
+
gap: compact ? "0.3vh" : "0.4vh"
|
|
4731
|
+
},
|
|
4732
|
+
children: [
|
|
4733
|
+
icon,
|
|
4734
|
+
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: color, children: label })
|
|
4735
|
+
]
|
|
4736
|
+
}
|
|
4737
|
+
) });
|
|
4738
|
+
}
|
|
4739
|
+
function WorldPositionSetButton({
|
|
4740
|
+
value,
|
|
4741
|
+
onChange,
|
|
4742
|
+
compact
|
|
4743
|
+
}) {
|
|
4744
|
+
const theme = useMantineTheme();
|
|
4745
|
+
const color = theme.colors[theme.primaryColor][5];
|
|
4746
|
+
const grab = async () => {
|
|
4747
|
+
try {
|
|
4748
|
+
const resp = await fetchNui("GET_POSITION", {}, value);
|
|
4749
|
+
if (!resp || typeof resp !== "object") return;
|
|
4750
|
+
onChange({
|
|
4751
|
+
x: Number(resp.x ?? 0),
|
|
4752
|
+
y: Number(resp.y ?? 0),
|
|
4753
|
+
z: Number(resp.z ?? 0),
|
|
4754
|
+
w: Number(resp.w ?? 0)
|
|
4755
|
+
});
|
|
4756
|
+
} catch {
|
|
4757
|
+
}
|
|
4758
|
+
};
|
|
4759
|
+
return /* @__PURE__ */ jsx(
|
|
4760
|
+
Vector4ActionButton,
|
|
4761
|
+
{
|
|
4762
|
+
icon: /* @__PURE__ */ jsx(Crosshair, { size: compact ? "1.1vh" : "1.3vh", color }),
|
|
4763
|
+
label: locale("Set"),
|
|
4764
|
+
tooltip: locale("SetWorldTooltip"),
|
|
4765
|
+
onClick: grab,
|
|
4766
|
+
color,
|
|
4767
|
+
compact
|
|
4768
|
+
}
|
|
4769
|
+
);
|
|
4770
|
+
}
|
|
4771
|
+
function WorldPositionGotoButton({
|
|
4772
|
+
value,
|
|
4773
|
+
compact
|
|
4774
|
+
}) {
|
|
4775
|
+
const theme = useMantineTheme();
|
|
4776
|
+
const color = theme.colors[theme.primaryColor][5];
|
|
4777
|
+
const goto = () => {
|
|
4778
|
+
fetchNui("GOTO_POSITION", value).catch(() => {
|
|
4779
|
+
});
|
|
4780
|
+
};
|
|
4781
|
+
return /* @__PURE__ */ jsx(
|
|
4782
|
+
Vector4ActionButton,
|
|
4783
|
+
{
|
|
4784
|
+
icon: /* @__PURE__ */ jsx(MapPin, { size: compact ? "1.1vh" : "1.3vh", color }),
|
|
4785
|
+
label: locale("Goto"),
|
|
4786
|
+
tooltip: locale("GotoWorldTooltip"),
|
|
4787
|
+
onClick: goto,
|
|
4788
|
+
color,
|
|
4789
|
+
compact
|
|
4790
|
+
}
|
|
4791
|
+
);
|
|
4792
|
+
}
|
|
4793
|
+
function Vector4DeleteButton({
|
|
4794
|
+
onClick,
|
|
4795
|
+
compact
|
|
4796
|
+
}) {
|
|
4797
|
+
const color = "#ef4444";
|
|
4798
|
+
return /* @__PURE__ */ jsx(
|
|
4799
|
+
Vector4ActionButton,
|
|
4800
|
+
{
|
|
4801
|
+
icon: /* @__PURE__ */ jsx(Trash2, { size: compact ? "1.1vh" : "1.3vh", color }),
|
|
4802
|
+
label: locale("Delete"),
|
|
4803
|
+
tooltip: locale("Delete"),
|
|
4804
|
+
onClick,
|
|
4805
|
+
color,
|
|
4806
|
+
compact
|
|
4807
|
+
}
|
|
4808
|
+
);
|
|
4809
|
+
}
|
|
4384
4810
|
var GroupSelectContext = createContext(null);
|
|
4385
4811
|
function GroupSelect({
|
|
4386
4812
|
value,
|
|
@@ -4832,6 +5258,6 @@ function TestBed({
|
|
|
4832
5258
|
);
|
|
4833
5259
|
}
|
|
4834
5260
|
|
|
4835
|
-
export { AdminPageTitle, AsyncSaveButton, BlipColorSelect, BlipDisplaySelect, BlipIconSelect, BorderedIcon, ConfigPanel, ConfirmModal, ControlMultiSelect, ControlSelect, Counter, FiveMKeyBindInput, FloatingParticles, GroupName, GroupRank, GroupSelect, InfoBox, InputContainer, LevelBanner, LevelPanel, Modal, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PositionPicker, PromptModal, SegmentedControl, SegmentedProgress, SelectItem, TestBed, Title, useModal, useModalActions, useNavigation, useNavigationStore };
|
|
5261
|
+
export { AdminPageTitle, AsyncSaveButton, BlipColorSelect, BlipDisplaySelect, BlipIconSelect, BorderedIcon, ConfigPanel, ConfirmModal, ControlMultiSelect, ControlSelect, Counter, FiveMKeyBindInput, FloatingParticles, GroupName, GroupRank, GroupSelect, InfoBox, InputContainer, LevelBanner, LevelPanel, MissingItemsBanner, Modal, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PositionPicker, PromptModal, SegmentedControl, SegmentedProgress, SelectItem, TestBed, Title, Vector4DeleteButton, Vector4Display, WorldPositionGotoButton, WorldPositionSetButton, useMissingItemsAudit, useModal, useModalActions, useNavigation, useNavigationStore };
|
|
4836
5262
|
//# sourceMappingURL=index.js.map
|
|
4837
5263
|
//# sourceMappingURL=index.js.map
|