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
|
@@ -9,6 +9,7 @@ var framerMotion = require('framer-motion');
|
|
|
9
9
|
var lucideReact = require('lucide-react');
|
|
10
10
|
var clickSoundUrl = require('../click_sound-PNCRRTM4.mp3');
|
|
11
11
|
var hoverSoundUrl = require('../hover_sound-NBUA222C.mp3');
|
|
12
|
+
var notifications = require('@mantine/notifications');
|
|
12
13
|
var reactQuery = require('@tanstack/react-query');
|
|
13
14
|
|
|
14
15
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -1235,11 +1236,11 @@ var colorNames = {
|
|
|
1235
1236
|
Yellow: { r: 255, g: 255, b: 0 },
|
|
1236
1237
|
YellowGreen: { r: 154, g: 205, b: 50 }
|
|
1237
1238
|
};
|
|
1238
|
-
function colorWithAlpha(color,
|
|
1239
|
+
function colorWithAlpha(color, alpha10) {
|
|
1239
1240
|
const lowerCasedColor = color.toLowerCase();
|
|
1240
1241
|
if (colorNames[lowerCasedColor]) {
|
|
1241
1242
|
const rgb = colorNames[lowerCasedColor];
|
|
1242
|
-
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${
|
|
1243
|
+
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha10})`;
|
|
1243
1244
|
}
|
|
1244
1245
|
if (/^#([A-Fa-f0-9]{6})$/.test(color)) {
|
|
1245
1246
|
const hex = color.slice(1);
|
|
@@ -1247,12 +1248,12 @@ function colorWithAlpha(color, alpha9) {
|
|
|
1247
1248
|
const r = bigint >> 16 & 255;
|
|
1248
1249
|
const g = bigint >> 8 & 255;
|
|
1249
1250
|
const b = bigint & 255;
|
|
1250
|
-
return `rgba(${r}, ${g}, ${b}, ${
|
|
1251
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha10})`;
|
|
1251
1252
|
}
|
|
1252
1253
|
if (/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/.test(color)) {
|
|
1253
1254
|
const result = color.match(/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/);
|
|
1254
1255
|
if (result) {
|
|
1255
|
-
return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${
|
|
1256
|
+
return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${alpha10})`;
|
|
1256
1257
|
}
|
|
1257
1258
|
}
|
|
1258
1259
|
return color;
|
|
@@ -3204,6 +3205,246 @@ function ConfirmModal({
|
|
|
3204
3205
|
}
|
|
3205
3206
|
) });
|
|
3206
3207
|
}
|
|
3208
|
+
var TABS = [
|
|
3209
|
+
{ id: "ox", label: "ox_inventory" },
|
|
3210
|
+
{ id: "qb", label: "qb-inventory" },
|
|
3211
|
+
{ id: "esx", label: "ESX legacy SQL" }
|
|
3212
|
+
];
|
|
3213
|
+
var useMissingItemsAudit = zustand.create((set, get) => ({
|
|
3214
|
+
data: null,
|
|
3215
|
+
loaded: false,
|
|
3216
|
+
inFlight: false,
|
|
3217
|
+
refresh: async () => {
|
|
3218
|
+
if (get().inFlight) return;
|
|
3219
|
+
set({ inFlight: true });
|
|
3220
|
+
try {
|
|
3221
|
+
const res = await fetchNui("GET_MISSING_ITEMS", void 0, {
|
|
3222
|
+
success: true,
|
|
3223
|
+
data: { missing: [], snippets: { ox: "", qb: "", esx: "" } }
|
|
3224
|
+
});
|
|
3225
|
+
if (res?.success && res.data) {
|
|
3226
|
+
set({ data: res.data, loaded: true });
|
|
3227
|
+
} else {
|
|
3228
|
+
set({ loaded: true });
|
|
3229
|
+
}
|
|
3230
|
+
} catch {
|
|
3231
|
+
set({ loaded: true });
|
|
3232
|
+
} finally {
|
|
3233
|
+
set({ inFlight: false });
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
}));
|
|
3237
|
+
function MissingItemsBanner() {
|
|
3238
|
+
const theme = core.useMantineTheme();
|
|
3239
|
+
const audit = useMissingItemsAudit((s) => s.data);
|
|
3240
|
+
const loaded = useMissingItemsAudit((s) => s.loaded);
|
|
3241
|
+
const inFlight = useMissingItemsAudit((s) => s.inFlight);
|
|
3242
|
+
const refresh = useMissingItemsAudit((s) => s.refresh);
|
|
3243
|
+
const [expanded, setExpanded] = react.useState(false);
|
|
3244
|
+
const [activeTab, setActiveTab] = react.useState("ox");
|
|
3245
|
+
const [hoveredTab, setHoveredTab] = react.useState(null);
|
|
3246
|
+
const [copied, setCopied] = react.useState(null);
|
|
3247
|
+
react.useEffect(() => {
|
|
3248
|
+
if (!loaded) refresh();
|
|
3249
|
+
}, [loaded, refresh]);
|
|
3250
|
+
const handleCopy = react.useCallback((tab) => {
|
|
3251
|
+
if (!audit) return;
|
|
3252
|
+
const text = audit.snippets[tab] ?? "";
|
|
3253
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
3254
|
+
setCopied(tab);
|
|
3255
|
+
setTimeout(() => setCopied((c) => c === tab ? null : c), 1500);
|
|
3256
|
+
}).catch(() => {
|
|
3257
|
+
});
|
|
3258
|
+
}, [audit]);
|
|
3259
|
+
const handleRefresh = react.useCallback((e) => {
|
|
3260
|
+
e.stopPropagation();
|
|
3261
|
+
refresh();
|
|
3262
|
+
}, [refresh]);
|
|
3263
|
+
if (!audit || audit.missing.length === 0) return null;
|
|
3264
|
+
const warnColor = "#f59e0b";
|
|
3265
|
+
const names = audit.missing.map((m) => m.name);
|
|
3266
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3267
|
+
"div",
|
|
3268
|
+
{
|
|
3269
|
+
style: {
|
|
3270
|
+
background: core.alpha(warnColor, 0.06),
|
|
3271
|
+
border: `0.1vh solid ${core.alpha(warnColor, 0.35)}`,
|
|
3272
|
+
borderLeft: `0.3vh solid ${warnColor}`,
|
|
3273
|
+
borderRadius: theme.radius.xs,
|
|
3274
|
+
margin: "0.6vh 1vh",
|
|
3275
|
+
overflow: "hidden"
|
|
3276
|
+
},
|
|
3277
|
+
children: [
|
|
3278
|
+
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "0.8vh", p: "0.8vh 1vh", style: { cursor: "pointer" }, onClick: () => setExpanded((e) => !e), children: [
|
|
3279
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { size: "1.8vh", color: warnColor, strokeWidth: 2.5 }),
|
|
3280
|
+
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { flex: 1, minWidth: 0 }, children: [
|
|
3281
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.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` }),
|
|
3282
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.5)", lineClamp: 1, style: { fontFamily: "monospace" }, children: names.join(", ") })
|
|
3283
|
+
] }),
|
|
3284
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3285
|
+
"button",
|
|
3286
|
+
{
|
|
3287
|
+
onClick: handleRefresh,
|
|
3288
|
+
disabled: inFlight,
|
|
3289
|
+
style: {
|
|
3290
|
+
background: "transparent",
|
|
3291
|
+
border: "none",
|
|
3292
|
+
padding: "0.3vh",
|
|
3293
|
+
cursor: inFlight ? "wait" : "pointer",
|
|
3294
|
+
display: "flex",
|
|
3295
|
+
alignItems: "center",
|
|
3296
|
+
justifyContent: "center",
|
|
3297
|
+
opacity: inFlight ? 0.4 : 0.7
|
|
3298
|
+
},
|
|
3299
|
+
title: "Re-check",
|
|
3300
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3301
|
+
framerMotion.motion.span,
|
|
3302
|
+
{
|
|
3303
|
+
animate: { rotate: inFlight ? 360 : 0 },
|
|
3304
|
+
transition: inFlight ? { duration: 1, repeat: Infinity, ease: "linear" } : { duration: 0 },
|
|
3305
|
+
style: { display: "flex", alignItems: "center", justifyContent: "center" },
|
|
3306
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { size: "1.5vh", color: core.alpha(warnColor, 0.7) })
|
|
3307
|
+
}
|
|
3308
|
+
)
|
|
3309
|
+
}
|
|
3310
|
+
),
|
|
3311
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3312
|
+
framerMotion.motion.div,
|
|
3313
|
+
{
|
|
3314
|
+
animate: { rotate: expanded ? 180 : 0 },
|
|
3315
|
+
transition: { duration: 0.18 },
|
|
3316
|
+
style: { display: "flex", alignItems: "center", justifyContent: "center" },
|
|
3317
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: "1.8vh", color: core.alpha(warnColor, 0.7) })
|
|
3318
|
+
}
|
|
3319
|
+
)
|
|
3320
|
+
] }),
|
|
3321
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { initial: false, children: expanded && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3322
|
+
framerMotion.motion.div,
|
|
3323
|
+
{
|
|
3324
|
+
initial: { height: 0, opacity: 0 },
|
|
3325
|
+
animate: { height: "auto", opacity: 1 },
|
|
3326
|
+
exit: { height: 0, opacity: 0 },
|
|
3327
|
+
transition: { duration: 0.18, ease: "easeOut" },
|
|
3328
|
+
style: { overflow: "hidden", borderTop: `0.1vh solid ${core.alpha(warnColor, 0.18)}` },
|
|
3329
|
+
children: [
|
|
3330
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Flex, { gap: "0", style: { borderBottom: `0.1vh solid ${core.alpha(warnColor, 0.18)}` }, children: TABS.map((tab) => {
|
|
3331
|
+
const active = tab.id === activeTab;
|
|
3332
|
+
const hovered = hoveredTab === tab.id;
|
|
3333
|
+
let bg = "transparent";
|
|
3334
|
+
if (active) bg = core.alpha(warnColor, 0.12);
|
|
3335
|
+
else if (hovered) bg = core.alpha(warnColor, 0.08);
|
|
3336
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3337
|
+
"button",
|
|
3338
|
+
{
|
|
3339
|
+
onClick: (e) => {
|
|
3340
|
+
e.stopPropagation();
|
|
3341
|
+
setActiveTab(tab.id);
|
|
3342
|
+
},
|
|
3343
|
+
onMouseEnter: () => setHoveredTab(tab.id),
|
|
3344
|
+
onMouseLeave: () => setHoveredTab((h) => h === tab.id ? null : h),
|
|
3345
|
+
style: {
|
|
3346
|
+
flex: 1,
|
|
3347
|
+
background: bg,
|
|
3348
|
+
border: "none",
|
|
3349
|
+
borderBottom: active ? `0.2vh solid ${warnColor}` : "0.2vh solid transparent",
|
|
3350
|
+
padding: "0.3vh 1vh",
|
|
3351
|
+
cursor: active ? "default" : "pointer",
|
|
3352
|
+
color: active ? warnColor : "rgba(255,255,255,0.5)",
|
|
3353
|
+
fontFamily: "Akrobat Bold",
|
|
3354
|
+
fontSize: "var(--mantine-font-size-xxs)",
|
|
3355
|
+
letterSpacing: "0.07em",
|
|
3356
|
+
textTransform: "uppercase",
|
|
3357
|
+
transition: "background 0.12s"
|
|
3358
|
+
},
|
|
3359
|
+
children: tab.label
|
|
3360
|
+
},
|
|
3361
|
+
tab.id
|
|
3362
|
+
);
|
|
3363
|
+
}) }),
|
|
3364
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3365
|
+
CodeView,
|
|
3366
|
+
{
|
|
3367
|
+
code: audit.snippets[activeTab] ?? "",
|
|
3368
|
+
copied: copied === activeTab,
|
|
3369
|
+
onCopy: (e) => {
|
|
3370
|
+
e.stopPropagation();
|
|
3371
|
+
handleCopy(activeTab);
|
|
3372
|
+
},
|
|
3373
|
+
warnColor
|
|
3374
|
+
}
|
|
3375
|
+
)
|
|
3376
|
+
]
|
|
3377
|
+
},
|
|
3378
|
+
"expanded"
|
|
3379
|
+
) })
|
|
3380
|
+
]
|
|
3381
|
+
}
|
|
3382
|
+
);
|
|
3383
|
+
}
|
|
3384
|
+
function CodeView({
|
|
3385
|
+
code,
|
|
3386
|
+
copied,
|
|
3387
|
+
onCopy,
|
|
3388
|
+
warnColor
|
|
3389
|
+
}) {
|
|
3390
|
+
const theme = core.useMantineTheme();
|
|
3391
|
+
const [hovered, setHovered] = react.useState(false);
|
|
3392
|
+
const lines = code === "" ? [""] : code.split("\n");
|
|
3393
|
+
const lineNumWidth = String(lines.length).length;
|
|
3394
|
+
const copyBg = copied ? core.alpha("#22c55e", 0.15) : hovered ? core.alpha(warnColor, 0.18) : core.alpha(warnColor, 0.1);
|
|
3395
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative" }, children: [
|
|
3396
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3397
|
+
"button",
|
|
3398
|
+
{
|
|
3399
|
+
onClick: onCopy,
|
|
3400
|
+
onMouseEnter: () => setHovered(true),
|
|
3401
|
+
onMouseLeave: () => setHovered(false),
|
|
3402
|
+
style: {
|
|
3403
|
+
position: "absolute",
|
|
3404
|
+
top: "0.6vh",
|
|
3405
|
+
right: "0.8vh",
|
|
3406
|
+
zIndex: 2,
|
|
3407
|
+
background: copyBg,
|
|
3408
|
+
border: `0.1vh solid ${core.alpha(copied ? "#22c55e" : warnColor, 0.35)}`,
|
|
3409
|
+
borderRadius: theme.radius.xs,
|
|
3410
|
+
padding: "0.4vh 0.7vh",
|
|
3411
|
+
cursor: "pointer",
|
|
3412
|
+
display: "flex",
|
|
3413
|
+
alignItems: "center",
|
|
3414
|
+
gap: "0.4vh",
|
|
3415
|
+
transition: "background 0.12s"
|
|
3416
|
+
},
|
|
3417
|
+
children: [
|
|
3418
|
+
copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: "1.4vh", color: "#22c55e" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { size: "1.4vh", color: warnColor }),
|
|
3419
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: copied ? "#22c55e" : warnColor, children: copied ? "Copied" : "Copy" })
|
|
3420
|
+
]
|
|
3421
|
+
}
|
|
3422
|
+
),
|
|
3423
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: {
|
|
3424
|
+
background: core.alpha(theme.colors.dark[9], 0.6),
|
|
3425
|
+
maxHeight: "40vh",
|
|
3426
|
+
overflowY: "auto",
|
|
3427
|
+
overflowX: "auto",
|
|
3428
|
+
padding: "0.6vh 0"
|
|
3429
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsx("table", { style: { borderCollapse: "collapse", width: "100%", fontFamily: "monospace", fontSize: "1.2vh", lineHeight: 1.5 }, children: /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: lines.map((line, i) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
3430
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { style: {
|
|
3431
|
+
width: `${lineNumWidth + 2}ch`,
|
|
3432
|
+
textAlign: "right",
|
|
3433
|
+
padding: "0 0.8vh 0 1vh",
|
|
3434
|
+
color: "rgba(255,255,255,0.25)",
|
|
3435
|
+
userSelect: "none",
|
|
3436
|
+
whiteSpace: "nowrap",
|
|
3437
|
+
verticalAlign: "top"
|
|
3438
|
+
}, children: i + 1 }),
|
|
3439
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { style: {
|
|
3440
|
+
padding: "0 1vh",
|
|
3441
|
+
color: "rgba(255,255,255,0.85)",
|
|
3442
|
+
whiteSpace: "pre",
|
|
3443
|
+
verticalAlign: "top"
|
|
3444
|
+
}, children: line || "\u200B" })
|
|
3445
|
+
] }, i)) }) }) })
|
|
3446
|
+
] });
|
|
3447
|
+
}
|
|
3207
3448
|
function getNested(obj, path) {
|
|
3208
3449
|
return path.split(".").reduce((acc, key) => acc ? acc[key] : void 0, obj);
|
|
3209
3450
|
}
|
|
@@ -3806,7 +4047,8 @@ function ConfigPanelInner({
|
|
|
3806
4047
|
resetConfirmText,
|
|
3807
4048
|
defaultConfig,
|
|
3808
4049
|
width,
|
|
3809
|
-
height
|
|
4050
|
+
height,
|
|
4051
|
+
suppressMissingItemsBanner
|
|
3810
4052
|
}) {
|
|
3811
4053
|
const { updateConfig, resetConfig, getHistory } = getScriptConfigInstance();
|
|
3812
4054
|
const form = useForm();
|
|
@@ -4029,18 +4271,21 @@ function ConfigPanelInner({
|
|
|
4029
4271
|
] })
|
|
4030
4272
|
] })
|
|
4031
4273
|
] }),
|
|
4032
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4033
|
-
|
|
4034
|
-
{
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4274
|
+
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: [
|
|
4275
|
+
!suppressMissingItemsBanner && /* @__PURE__ */ jsxRuntime.jsx(MissingItemsBanner, {}),
|
|
4276
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4277
|
+
framerMotion.motion.div,
|
|
4278
|
+
{
|
|
4279
|
+
initial: firstMountRef.current ? (firstMountRef.current = false, false) : { opacity: 0, y: 4 },
|
|
4280
|
+
animate: { opacity: 1, y: 0 },
|
|
4281
|
+
exit: { opacity: 0, y: -4 },
|
|
4282
|
+
transition: { duration: 0.15 },
|
|
4283
|
+
style: { flex: 1, display: "flex", flexDirection: "column", overflowY: "auto" },
|
|
4284
|
+
children: children(activeTab)
|
|
4285
|
+
},
|
|
4286
|
+
activeTab
|
|
4287
|
+
) })
|
|
4288
|
+
] })
|
|
4044
4289
|
]
|
|
4045
4290
|
}
|
|
4046
4291
|
)
|
|
@@ -4082,12 +4327,26 @@ function ConfigPanel(props) {
|
|
|
4082
4327
|
if (result?.success) {
|
|
4083
4328
|
form.reinitialize(cloneConfig(form.values));
|
|
4084
4329
|
configPanelQueryClient.invalidateQueries({ queryKey: ["scriptConfigHistory"] });
|
|
4330
|
+
useMissingItemsAudit.getState().refresh();
|
|
4331
|
+
notifications.notifications.show({
|
|
4332
|
+
color: "green",
|
|
4333
|
+
title: locale("ConfigSaveSuccessTitle"),
|
|
4334
|
+
message: locale("ConfigSaveSuccessBody"),
|
|
4335
|
+
autoClose: 3e3
|
|
4336
|
+
});
|
|
4085
4337
|
return;
|
|
4086
4338
|
}
|
|
4087
4339
|
form.reinitialize(cloneConfig(store.getState()));
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4340
|
+
const err = result?._error || "Unknown";
|
|
4341
|
+
console.warn(`[ConfigPanel] config save failed: ${err}`);
|
|
4342
|
+
const titleKey = err === "NoPermission" ? "ConfigSaveNoPermissionTitle" : err === "VersionConflict" ? "ConfigSaveVersionConflictTitle" : err === "NotReady" ? "ConfigSaveNotReadyTitle" : "ConfigSaveFailedTitle";
|
|
4343
|
+
const bodyKey = err === "NoPermission" ? "ConfigSaveNoPermissionBody" : err === "VersionConflict" ? "ConfigSaveVersionConflictBody" : err === "NotReady" ? "ConfigSaveNotReadyBody" : "ConfigSaveFailedBody";
|
|
4344
|
+
notifications.notifications.show({
|
|
4345
|
+
color: "red",
|
|
4346
|
+
title: locale(titleKey),
|
|
4347
|
+
message: locale(bodyKey, err),
|
|
4348
|
+
autoClose: 6e3
|
|
4349
|
+
});
|
|
4091
4350
|
} finally {
|
|
4092
4351
|
setIsSaving(false);
|
|
4093
4352
|
}
|
|
@@ -4106,6 +4365,7 @@ function ConfigPanel(props) {
|
|
|
4106
4365
|
}
|
|
4107
4366
|
) });
|
|
4108
4367
|
}
|
|
4368
|
+
var MISSING_COLOR = "#f59e0b";
|
|
4109
4369
|
function LazyImage({ src, style }) {
|
|
4110
4370
|
const [visible, setVisible] = react.useState(false);
|
|
4111
4371
|
const ref = react.useRef(null);
|
|
@@ -4123,14 +4383,19 @@ function LazyImage({ src, style }) {
|
|
|
4123
4383
|
}
|
|
4124
4384
|
function SelectItem(props) {
|
|
4125
4385
|
const invItems = useItems();
|
|
4386
|
+
const isMissing = !!props.value && !invItems[props.value];
|
|
4126
4387
|
const formattedItems = react.useMemo(() => {
|
|
4127
4388
|
const seen = /* @__PURE__ */ new Set();
|
|
4128
|
-
|
|
4389
|
+
const list = useItemsList(props.excludeItemNames ?? []).filter((item) => {
|
|
4129
4390
|
if (seen.has(item.name)) return false;
|
|
4130
4391
|
seen.add(item.name);
|
|
4131
4392
|
return true;
|
|
4132
4393
|
}).map((item) => ({ value: item.name, label: item.label, image: item.image }));
|
|
4133
|
-
|
|
4394
|
+
if (isMissing) {
|
|
4395
|
+
list.unshift({ value: props.value, label: props.value, image: "" });
|
|
4396
|
+
}
|
|
4397
|
+
return list;
|
|
4398
|
+
}, [invItems, props.excludeItemNames, props.value, isMissing]);
|
|
4134
4399
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4135
4400
|
core.Select,
|
|
4136
4401
|
{
|
|
@@ -4145,10 +4410,11 @@ function SelectItem(props) {
|
|
|
4145
4410
|
data: formattedItems,
|
|
4146
4411
|
allowDeselect: false,
|
|
4147
4412
|
searchable: true,
|
|
4413
|
+
styles: isMissing ? { input: { color: MISSING_COLOR } } : void 0,
|
|
4148
4414
|
comboboxProps: { withinPortal: true, zIndex: 2e3 },
|
|
4149
4415
|
leftSectionWidth: "4vh",
|
|
4150
4416
|
leftSectionPointerEvents: "none",
|
|
4151
|
-
leftSection: props.value ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4417
|
+
leftSection: isMissing ? /* @__PURE__ */ jsxRuntime.jsx(core.Flex, { align: "center", justify: "center", w: "4vh", h: "4vh", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { size: "2vh", color: MISSING_COLOR, strokeWidth: 2.5 }) }) : props.value ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4152
4418
|
core.Image,
|
|
4153
4419
|
{
|
|
4154
4420
|
fallbackSrc: "/placeholder.png",
|
|
@@ -4159,19 +4425,37 @@ function SelectItem(props) {
|
|
|
4159
4425
|
}
|
|
4160
4426
|
) : null,
|
|
4161
4427
|
nothingFoundMessage: locale("NoItemsFound"),
|
|
4162
|
-
renderOption: (item) =>
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
{
|
|
4166
|
-
|
|
4167
|
-
style: {
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4428
|
+
renderOption: (item) => {
|
|
4429
|
+
const optionMissing = !invItems[item.option.value] && item.option.value === props.value;
|
|
4430
|
+
if (optionMissing) {
|
|
4431
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "xs", w: "100%", children: [
|
|
4432
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Flex, { align: "center", justify: "center", w: "4vh", h: "4vh", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { size: "2vh", color: MISSING_COLOR, strokeWidth: 2.5 }) }),
|
|
4433
|
+
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { flex: 1, minWidth: 0 }, children: [
|
|
4434
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { size: "sm", c: MISSING_COLOR, style: { fontFamily: "monospace" }, children: item.option.value }),
|
|
4435
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { size: "xxs", c: "dimmed", children: locale("ItemNotInInventory") })
|
|
4436
|
+
] }),
|
|
4437
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: {
|
|
4438
|
+
background: "rgba(245,158,11,0.12)",
|
|
4439
|
+
border: `0.1vh solid ${MISSING_COLOR}59`,
|
|
4440
|
+
borderRadius: "0.3vh",
|
|
4441
|
+
padding: "0.1vh 0.6vh"
|
|
4442
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsx(core.Text, { size: "xxs", c: MISSING_COLOR, ff: "Akrobat Bold", tt: "uppercase", lts: "0.06em", children: locale("Missing") }) })
|
|
4443
|
+
] });
|
|
4444
|
+
}
|
|
4445
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "xs", w: "100%", children: [
|
|
4446
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4447
|
+
LazyImage,
|
|
4448
|
+
{
|
|
4449
|
+
src: invItems[item.option.value]?.image || "",
|
|
4450
|
+
style: { aspectRatio: "1 / 1" }
|
|
4451
|
+
}
|
|
4452
|
+
),
|
|
4453
|
+
/* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", children: [
|
|
4454
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { size: "sm", children: item.option.label }),
|
|
4455
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { size: "xxs", c: "dimmed", children: item.option.value })
|
|
4456
|
+
] })
|
|
4457
|
+
] });
|
|
4458
|
+
}
|
|
4175
4459
|
}
|
|
4176
4460
|
);
|
|
4177
4461
|
}
|
|
@@ -4388,6 +4672,148 @@ function PickerButton({
|
|
|
4388
4672
|
}
|
|
4389
4673
|
) });
|
|
4390
4674
|
}
|
|
4675
|
+
function fmtV4(n) {
|
|
4676
|
+
return Number.isFinite(n) ? n.toFixed(2) : "0.00";
|
|
4677
|
+
}
|
|
4678
|
+
function Vector4Display({ value }) {
|
|
4679
|
+
const theme = core.useMantineTheme();
|
|
4680
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4681
|
+
core.Flex,
|
|
4682
|
+
{
|
|
4683
|
+
align: "center",
|
|
4684
|
+
gap: "xs",
|
|
4685
|
+
p: "xs",
|
|
4686
|
+
style: {
|
|
4687
|
+
background: core.alpha(theme.colors.dark[5], 0.35),
|
|
4688
|
+
border: "0.1vh solid rgba(255,255,255,0.05)",
|
|
4689
|
+
borderRadius: theme.radius.xs
|
|
4690
|
+
},
|
|
4691
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4692
|
+
core.Text,
|
|
4693
|
+
{
|
|
4694
|
+
ff: "monospace",
|
|
4695
|
+
size: "xxs",
|
|
4696
|
+
c: "rgba(255,255,255,0.85)",
|
|
4697
|
+
style: { flex: 1, letterSpacing: "0.02em", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" },
|
|
4698
|
+
children: [
|
|
4699
|
+
"vector4(",
|
|
4700
|
+
fmtV4(value.x),
|
|
4701
|
+
", ",
|
|
4702
|
+
fmtV4(value.y),
|
|
4703
|
+
", ",
|
|
4704
|
+
fmtV4(value.z),
|
|
4705
|
+
", ",
|
|
4706
|
+
fmtV4(value.w),
|
|
4707
|
+
")"
|
|
4708
|
+
]
|
|
4709
|
+
}
|
|
4710
|
+
)
|
|
4711
|
+
}
|
|
4712
|
+
);
|
|
4713
|
+
}
|
|
4714
|
+
function Vector4ActionButton({
|
|
4715
|
+
icon,
|
|
4716
|
+
label,
|
|
4717
|
+
tooltip,
|
|
4718
|
+
onClick,
|
|
4719
|
+
color,
|
|
4720
|
+
compact
|
|
4721
|
+
}) {
|
|
4722
|
+
const theme = core.useMantineTheme();
|
|
4723
|
+
return /* @__PURE__ */ jsxRuntime.jsx(core.Tooltip, { label: tooltip, position: "top", withArrow: true, withinPortal: true, zIndex: 2e3, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4724
|
+
framerMotion.motion.button,
|
|
4725
|
+
{
|
|
4726
|
+
onClick,
|
|
4727
|
+
whileHover: { background: core.alpha(color, 0.18) },
|
|
4728
|
+
whileTap: { scale: 0.95 },
|
|
4729
|
+
style: {
|
|
4730
|
+
background: core.alpha(color, 0.1),
|
|
4731
|
+
border: `0.1vh solid ${core.alpha(color, 0.35)}`,
|
|
4732
|
+
borderRadius: theme.radius.xs,
|
|
4733
|
+
padding: compact ? "0.25vh 0.6vh" : "0.5vh 0.8vh",
|
|
4734
|
+
cursor: "pointer",
|
|
4735
|
+
display: "flex",
|
|
4736
|
+
alignItems: "center",
|
|
4737
|
+
gap: compact ? "0.3vh" : "0.4vh"
|
|
4738
|
+
},
|
|
4739
|
+
children: [
|
|
4740
|
+
icon,
|
|
4741
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: color, children: label })
|
|
4742
|
+
]
|
|
4743
|
+
}
|
|
4744
|
+
) });
|
|
4745
|
+
}
|
|
4746
|
+
function WorldPositionSetButton({
|
|
4747
|
+
value,
|
|
4748
|
+
onChange,
|
|
4749
|
+
compact
|
|
4750
|
+
}) {
|
|
4751
|
+
const theme = core.useMantineTheme();
|
|
4752
|
+
const color = theme.colors[theme.primaryColor][5];
|
|
4753
|
+
const grab = async () => {
|
|
4754
|
+
try {
|
|
4755
|
+
const resp = await fetchNui("GET_POSITION", {}, value);
|
|
4756
|
+
if (!resp || typeof resp !== "object") return;
|
|
4757
|
+
onChange({
|
|
4758
|
+
x: Number(resp.x ?? 0),
|
|
4759
|
+
y: Number(resp.y ?? 0),
|
|
4760
|
+
z: Number(resp.z ?? 0),
|
|
4761
|
+
w: Number(resp.w ?? 0)
|
|
4762
|
+
});
|
|
4763
|
+
} catch {
|
|
4764
|
+
}
|
|
4765
|
+
};
|
|
4766
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4767
|
+
Vector4ActionButton,
|
|
4768
|
+
{
|
|
4769
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crosshair, { size: compact ? "1.1vh" : "1.3vh", color }),
|
|
4770
|
+
label: locale("Set"),
|
|
4771
|
+
tooltip: locale("SetWorldTooltip"),
|
|
4772
|
+
onClick: grab,
|
|
4773
|
+
color,
|
|
4774
|
+
compact
|
|
4775
|
+
}
|
|
4776
|
+
);
|
|
4777
|
+
}
|
|
4778
|
+
function WorldPositionGotoButton({
|
|
4779
|
+
value,
|
|
4780
|
+
compact
|
|
4781
|
+
}) {
|
|
4782
|
+
const theme = core.useMantineTheme();
|
|
4783
|
+
const color = theme.colors[theme.primaryColor][5];
|
|
4784
|
+
const goto = () => {
|
|
4785
|
+
fetchNui("GOTO_POSITION", value).catch(() => {
|
|
4786
|
+
});
|
|
4787
|
+
};
|
|
4788
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4789
|
+
Vector4ActionButton,
|
|
4790
|
+
{
|
|
4791
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MapPin, { size: compact ? "1.1vh" : "1.3vh", color }),
|
|
4792
|
+
label: locale("Goto"),
|
|
4793
|
+
tooltip: locale("GotoWorldTooltip"),
|
|
4794
|
+
onClick: goto,
|
|
4795
|
+
color,
|
|
4796
|
+
compact
|
|
4797
|
+
}
|
|
4798
|
+
);
|
|
4799
|
+
}
|
|
4800
|
+
function Vector4DeleteButton({
|
|
4801
|
+
onClick,
|
|
4802
|
+
compact
|
|
4803
|
+
}) {
|
|
4804
|
+
const color = "#ef4444";
|
|
4805
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4806
|
+
Vector4ActionButton,
|
|
4807
|
+
{
|
|
4808
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { size: compact ? "1.1vh" : "1.3vh", color }),
|
|
4809
|
+
label: locale("Delete"),
|
|
4810
|
+
tooltip: locale("Delete"),
|
|
4811
|
+
onClick,
|
|
4812
|
+
color,
|
|
4813
|
+
compact
|
|
4814
|
+
}
|
|
4815
|
+
);
|
|
4816
|
+
}
|
|
4391
4817
|
var GroupSelectContext = react.createContext(null);
|
|
4392
4818
|
function GroupSelect({
|
|
4393
4819
|
value,
|
|
@@ -4859,6 +5285,7 @@ exports.InfoBox = InfoBox;
|
|
|
4859
5285
|
exports.InputContainer = InputContainer;
|
|
4860
5286
|
exports.LevelBanner = LevelBanner;
|
|
4861
5287
|
exports.LevelPanel = LevelPanel;
|
|
5288
|
+
exports.MissingItemsBanner = MissingItemsBanner;
|
|
4862
5289
|
exports.Modal = Modal;
|
|
4863
5290
|
exports.ModalContext = ModalContext;
|
|
4864
5291
|
exports.ModalProvider = ModalProvider;
|
|
@@ -4876,6 +5303,11 @@ exports.SegmentedProgress = SegmentedProgress;
|
|
|
4876
5303
|
exports.SelectItem = SelectItem;
|
|
4877
5304
|
exports.TestBed = TestBed;
|
|
4878
5305
|
exports.Title = Title;
|
|
5306
|
+
exports.Vector4DeleteButton = Vector4DeleteButton;
|
|
5307
|
+
exports.Vector4Display = Vector4Display;
|
|
5308
|
+
exports.WorldPositionGotoButton = WorldPositionGotoButton;
|
|
5309
|
+
exports.WorldPositionSetButton = WorldPositionSetButton;
|
|
5310
|
+
exports.useMissingItemsAudit = useMissingItemsAudit;
|
|
4879
5311
|
exports.useModal = useModal;
|
|
4880
5312
|
exports.useModalActions = useModalActions;
|
|
4881
5313
|
exports.useNavigation = useNavigation;
|