dirk-cfx-react 1.1.71 → 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/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- export { AdminPageTitle, AdminPageTitleProps, AsyncSaveButton, BlipColorSelect, BlipColorSelectProps, BlipDisplaySelect, BlipDisplaySelectProps, BlipIconSelect, BlipIconSelectProps, BorderedIcon, BorderedIconProps, ButtonProps, ConfigPanel, ConfigPanelProps, ConfirmModal, ConfirmModalProps, ControlMultiSelect, ControlMultiSelectProps, ControlSelect, ControlSelectProps, Counter, FiveMControls, FiveMKeyBindInput, FloatingParticles, FloatingParticlesProps, GroupName, GroupNameProps, GroupRank, GroupRankProps, GroupSelect, GroupSelectProps, GroupType, GroupValue, InfoBox, InfoBoxProps, InputContainer, InputContainerProps, LevelBanner, LevelPanel, Modal, ModalContext, ModalProps, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavItem, NavigationContext, NavigationProvider, NavigationStore, ParticleState, PositionPicker, PositionPickerProps, ProgressProps, Prompt, PromptButton, PromptModal, SegmentProps, SegmentedControl, SegmentedControlProps, SegmentedProgress, SelectItem, SelectItemProps, StoreModalProps, TestBed, TestBedItem, TestBedProps, Title, TitleProps, Vector4DeleteButton, Vector4Display, Vector4Value, WorldPositionGotoButton, WorldPositionSetButton, useModal, useModalActions, useNavigation, useNavigationStore } from './components/index.cjs';
1
+ export { AdminPageTitle, AdminPageTitleProps, AsyncSaveButton, BlipColorSelect, BlipColorSelectProps, BlipDisplaySelect, BlipDisplaySelectProps, BlipIconSelect, BlipIconSelectProps, BorderedIcon, BorderedIconProps, ButtonProps, ConfigPanel, ConfigPanelProps, ConfirmModal, ConfirmModalProps, ControlMultiSelect, ControlMultiSelectProps, ControlSelect, ControlSelectProps, Counter, FiveMControls, FiveMKeyBindInput, FloatingParticles, FloatingParticlesProps, GroupName, GroupNameProps, GroupRank, GroupRankProps, GroupSelect, GroupSelectProps, GroupType, GroupValue, InfoBox, InfoBoxProps, InputContainer, InputContainerProps, LevelBanner, LevelPanel, MissingItemsBanner, Modal, ModalContext, ModalProps, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavItem, NavigationContext, NavigationProvider, NavigationStore, ParticleState, PositionPicker, PositionPickerProps, ProgressProps, Prompt, PromptButton, PromptModal, SegmentProps, SegmentedControl, SegmentedControlProps, SegmentedProgress, SelectItem, SelectItemProps, StoreModalProps, TestBed, TestBedItem, TestBedProps, Title, TitleProps, Vector4DeleteButton, Vector4Display, Vector4Value, WorldPositionGotoButton, WorldPositionSetButton, useMissingItemsAudit, useModal, useModalActions, useNavigation, useNavigationStore } from './components/index.cjs';
2
2
  export { FrameworkGrade, FrameworkGroup, GTA_CONTROLS, GTA_CONTROL_GROUP_ORDER, GtaControl, GtaControlGroup, INPUT_MAPPER_KEYS_BY_PRIMARY, INPUT_MAPPER_PRIMARY_OPTIONS, InitialFetch, InternalEvent, InventoryItem, InventoryItems, SettingsState, SkillSettings, UploadImageProps, colorWithAlpha, copyToClipboard, createSkill, extractDefaults, fetchLuaTable, fetchNui, formatGtaControl, gameToMap, getGtaControl, getImageShape, getItemImageUrl, initialFetches, internalEvent, isEnvBrowser, isProfanity, latPr100, locale, localeStore, mapCenter, mapToGame, noop, numberToRoman, openLink, registerInitialFetch, registerInitialLuaTableFetch, runFetches, selectAllGroups, splitFAString, updatePresignedURL, uploadImage, useAutoFetcher, useFrameworkGroups, useItems, useItemsList, useProfanityStore, useSettings } from './utils/index.cjs';
3
3
  export { FormProvider, FormState, NuiHandlerSignature, NuiMessageData, ScriptConfigHistoryChange, ScriptConfigHistoryEntry, ScriptConfigHistoryRequest, ScriptConfigHistoryResponse, ScriptConfigInstance, TornEdgeSVGFilter, ValidationRules, ValidatorFn, createFormStore, createScriptConfig, getScriptConfigInstance, useAudio, useForm, useFormActions, useFormError, useFormErrors, useFormField, useFormFields, useNuiEvent, useTornEdges } from './hooks/index.cjs';
4
4
  export { DirkProvider, DirkProviderProps } from './providers/index.cjs';
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { AdminPageTitle, AdminPageTitleProps, AsyncSaveButton, BlipColorSelect, BlipColorSelectProps, BlipDisplaySelect, BlipDisplaySelectProps, BlipIconSelect, BlipIconSelectProps, BorderedIcon, BorderedIconProps, ButtonProps, ConfigPanel, ConfigPanelProps, ConfirmModal, ConfirmModalProps, ControlMultiSelect, ControlMultiSelectProps, ControlSelect, ControlSelectProps, Counter, FiveMControls, FiveMKeyBindInput, FloatingParticles, FloatingParticlesProps, GroupName, GroupNameProps, GroupRank, GroupRankProps, GroupSelect, GroupSelectProps, GroupType, GroupValue, InfoBox, InfoBoxProps, InputContainer, InputContainerProps, LevelBanner, LevelPanel, Modal, ModalContext, ModalProps, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavItem, NavigationContext, NavigationProvider, NavigationStore, ParticleState, PositionPicker, PositionPickerProps, ProgressProps, Prompt, PromptButton, PromptModal, SegmentProps, SegmentedControl, SegmentedControlProps, SegmentedProgress, SelectItem, SelectItemProps, StoreModalProps, TestBed, TestBedItem, TestBedProps, Title, TitleProps, Vector4DeleteButton, Vector4Display, Vector4Value, WorldPositionGotoButton, WorldPositionSetButton, useModal, useModalActions, useNavigation, useNavigationStore } from './components/index.js';
1
+ export { AdminPageTitle, AdminPageTitleProps, AsyncSaveButton, BlipColorSelect, BlipColorSelectProps, BlipDisplaySelect, BlipDisplaySelectProps, BlipIconSelect, BlipIconSelectProps, BorderedIcon, BorderedIconProps, ButtonProps, ConfigPanel, ConfigPanelProps, ConfirmModal, ConfirmModalProps, ControlMultiSelect, ControlMultiSelectProps, ControlSelect, ControlSelectProps, Counter, FiveMControls, FiveMKeyBindInput, FloatingParticles, FloatingParticlesProps, GroupName, GroupNameProps, GroupRank, GroupRankProps, GroupSelect, GroupSelectProps, GroupType, GroupValue, InfoBox, InfoBoxProps, InputContainer, InputContainerProps, LevelBanner, LevelPanel, MissingItemsBanner, Modal, ModalContext, ModalProps, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavItem, NavigationContext, NavigationProvider, NavigationStore, ParticleState, PositionPicker, PositionPickerProps, ProgressProps, Prompt, PromptButton, PromptModal, SegmentProps, SegmentedControl, SegmentedControlProps, SegmentedProgress, SelectItem, SelectItemProps, StoreModalProps, TestBed, TestBedItem, TestBedProps, Title, TitleProps, Vector4DeleteButton, Vector4Display, Vector4Value, WorldPositionGotoButton, WorldPositionSetButton, useMissingItemsAudit, useModal, useModalActions, useNavigation, useNavigationStore } from './components/index.js';
2
2
  export { FrameworkGrade, FrameworkGroup, GTA_CONTROLS, GTA_CONTROL_GROUP_ORDER, GtaControl, GtaControlGroup, INPUT_MAPPER_KEYS_BY_PRIMARY, INPUT_MAPPER_PRIMARY_OPTIONS, InitialFetch, InternalEvent, InventoryItem, InventoryItems, SettingsState, SkillSettings, UploadImageProps, colorWithAlpha, copyToClipboard, createSkill, extractDefaults, fetchLuaTable, fetchNui, formatGtaControl, gameToMap, getGtaControl, getImageShape, getItemImageUrl, initialFetches, internalEvent, isEnvBrowser, isProfanity, latPr100, locale, localeStore, mapCenter, mapToGame, noop, numberToRoman, openLink, registerInitialFetch, registerInitialLuaTableFetch, runFetches, selectAllGroups, splitFAString, updatePresignedURL, uploadImage, useAutoFetcher, useFrameworkGroups, useItems, useItemsList, useProfanityStore, useSettings } from './utils/index.js';
3
3
  export { FormProvider, FormState, NuiHandlerSignature, NuiMessageData, ScriptConfigHistoryChange, ScriptConfigHistoryEntry, ScriptConfigHistoryRequest, ScriptConfigHistoryResponse, ScriptConfigInstance, TornEdgeSVGFilter, ValidationRules, ValidatorFn, createFormStore, createScriptConfig, getScriptConfigInstance, useAudio, useForm, useFormActions, useFormError, useFormErrors, useFormField, useFormFields, useNuiEvent, useTornEdges } from './hooks/index.js';
4
4
  export { DirkProvider, DirkProviderProps } from './providers/index.js';
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { Flex, Text, Image as Image$1, createTheme, Box, Stack, Title as Title$1, Code, TextInput, Select, useMantineTheme, Tooltip, alpha, Progress, RingProgress, Portal, Button, NumberInput, MultiSelect, Loader, ActionIcon, MantineProvider, BackgroundImage, Group, JsonInput } from '@mantine/core';
2
2
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
- import React6, { createContext, useContext, useEffect, useRef, useState, useMemo, useLayoutEffect } from 'react';
3
+ import React6, { createContext, useContext, useEffect, useRef, 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, MapPin, Crosshair, EyeOff, Eye, RotateCcw, Check, FlaskConical, ChevronUp, ChevronDown, 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, 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';
@@ -1242,11 +1242,11 @@ var colorNames = {
1242
1242
  Yellow: { r: 255, g: 255, b: 0 },
1243
1243
  YellowGreen: { r: 154, g: 205, b: 50 }
1244
1244
  };
1245
- function colorWithAlpha(color, alpha9) {
1245
+ function colorWithAlpha(color, alpha10) {
1246
1246
  const lowerCasedColor = color.toLowerCase();
1247
1247
  if (colorNames[lowerCasedColor]) {
1248
1248
  const rgb = colorNames[lowerCasedColor];
1249
- return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha9})`;
1249
+ return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha10})`;
1250
1250
  }
1251
1251
  if (/^#([A-Fa-f0-9]{6})$/.test(color)) {
1252
1252
  const hex = color.slice(1);
@@ -1254,12 +1254,12 @@ function colorWithAlpha(color, alpha9) {
1254
1254
  const r = bigint >> 16 & 255;
1255
1255
  const g = bigint >> 8 & 255;
1256
1256
  const b = bigint & 255;
1257
- return `rgba(${r}, ${g}, ${b}, ${alpha9})`;
1257
+ return `rgba(${r}, ${g}, ${b}, ${alpha10})`;
1258
1258
  }
1259
1259
  if (/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/.test(color)) {
1260
1260
  const result = color.match(/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/);
1261
1261
  if (result) {
1262
- return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${alpha9})`;
1262
+ return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${alpha10})`;
1263
1263
  }
1264
1264
  }
1265
1265
  return color;
@@ -3807,6 +3807,246 @@ function ConfirmModal({
3807
3807
  }
3808
3808
  ) });
3809
3809
  }
3810
+ var TABS = [
3811
+ { id: "ox", label: "ox_inventory" },
3812
+ { id: "qb", label: "qb-inventory" },
3813
+ { id: "esx", label: "ESX legacy SQL" }
3814
+ ];
3815
+ var useMissingItemsAudit = create((set, get) => ({
3816
+ data: null,
3817
+ loaded: false,
3818
+ inFlight: false,
3819
+ refresh: async () => {
3820
+ if (get().inFlight) return;
3821
+ set({ inFlight: true });
3822
+ try {
3823
+ const res = await fetchNui("GET_MISSING_ITEMS", void 0, {
3824
+ success: true,
3825
+ data: { missing: [], snippets: { ox: "", qb: "", esx: "" } }
3826
+ });
3827
+ if (res?.success && res.data) {
3828
+ set({ data: res.data, loaded: true });
3829
+ } else {
3830
+ set({ loaded: true });
3831
+ }
3832
+ } catch {
3833
+ set({ loaded: true });
3834
+ } finally {
3835
+ set({ inFlight: false });
3836
+ }
3837
+ }
3838
+ }));
3839
+ function MissingItemsBanner() {
3840
+ const theme2 = useMantineTheme();
3841
+ const audit = useMissingItemsAudit((s) => s.data);
3842
+ const loaded = useMissingItemsAudit((s) => s.loaded);
3843
+ const inFlight = useMissingItemsAudit((s) => s.inFlight);
3844
+ const refresh = useMissingItemsAudit((s) => s.refresh);
3845
+ const [expanded, setExpanded] = useState(false);
3846
+ const [activeTab, setActiveTab] = useState("ox");
3847
+ const [hoveredTab, setHoveredTab] = useState(null);
3848
+ const [copied, setCopied] = useState(null);
3849
+ useEffect(() => {
3850
+ if (!loaded) refresh();
3851
+ }, [loaded, refresh]);
3852
+ const handleCopy = useCallback((tab) => {
3853
+ if (!audit) return;
3854
+ const text = audit.snippets[tab] ?? "";
3855
+ navigator.clipboard.writeText(text).then(() => {
3856
+ setCopied(tab);
3857
+ setTimeout(() => setCopied((c) => c === tab ? null : c), 1500);
3858
+ }).catch(() => {
3859
+ });
3860
+ }, [audit]);
3861
+ const handleRefresh = useCallback((e) => {
3862
+ e.stopPropagation();
3863
+ refresh();
3864
+ }, [refresh]);
3865
+ if (!audit || audit.missing.length === 0) return null;
3866
+ const warnColor = "#f59e0b";
3867
+ const names = audit.missing.map((m) => m.name);
3868
+ return /* @__PURE__ */ jsxs(
3869
+ "div",
3870
+ {
3871
+ style: {
3872
+ background: alpha(warnColor, 0.06),
3873
+ border: `0.1vh solid ${alpha(warnColor, 0.35)}`,
3874
+ borderLeft: `0.3vh solid ${warnColor}`,
3875
+ borderRadius: theme2.radius.xs,
3876
+ margin: "0.6vh 1vh",
3877
+ overflow: "hidden"
3878
+ },
3879
+ children: [
3880
+ /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "0.8vh", p: "0.8vh 1vh", style: { cursor: "pointer" }, onClick: () => setExpanded((e) => !e), children: [
3881
+ /* @__PURE__ */ jsx(AlertTriangle, { size: "1.8vh", color: warnColor, strokeWidth: 2.5 }),
3882
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", style: { flex: 1, minWidth: 0 }, children: [
3883
+ /* @__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` }),
3884
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.5)", lineClamp: 1, style: { fontFamily: "monospace" }, children: names.join(", ") })
3885
+ ] }),
3886
+ /* @__PURE__ */ jsx(
3887
+ "button",
3888
+ {
3889
+ onClick: handleRefresh,
3890
+ disabled: inFlight,
3891
+ style: {
3892
+ background: "transparent",
3893
+ border: "none",
3894
+ padding: "0.3vh",
3895
+ cursor: inFlight ? "wait" : "pointer",
3896
+ display: "flex",
3897
+ alignItems: "center",
3898
+ justifyContent: "center",
3899
+ opacity: inFlight ? 0.4 : 0.7
3900
+ },
3901
+ title: "Re-check",
3902
+ children: /* @__PURE__ */ jsx(
3903
+ motion.span,
3904
+ {
3905
+ animate: { rotate: inFlight ? 360 : 0 },
3906
+ transition: inFlight ? { duration: 1, repeat: Infinity, ease: "linear" } : { duration: 0 },
3907
+ style: { display: "flex", alignItems: "center", justifyContent: "center" },
3908
+ children: /* @__PURE__ */ jsx(RefreshCw, { size: "1.5vh", color: alpha(warnColor, 0.7) })
3909
+ }
3910
+ )
3911
+ }
3912
+ ),
3913
+ /* @__PURE__ */ jsx(
3914
+ motion.div,
3915
+ {
3916
+ animate: { rotate: expanded ? 180 : 0 },
3917
+ transition: { duration: 0.18 },
3918
+ style: { display: "flex", alignItems: "center", justifyContent: "center" },
3919
+ children: /* @__PURE__ */ jsx(ChevronDown, { size: "1.8vh", color: alpha(warnColor, 0.7) })
3920
+ }
3921
+ )
3922
+ ] }),
3923
+ /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: expanded && /* @__PURE__ */ jsxs(
3924
+ motion.div,
3925
+ {
3926
+ initial: { height: 0, opacity: 0 },
3927
+ animate: { height: "auto", opacity: 1 },
3928
+ exit: { height: 0, opacity: 0 },
3929
+ transition: { duration: 0.18, ease: "easeOut" },
3930
+ style: { overflow: "hidden", borderTop: `0.1vh solid ${alpha(warnColor, 0.18)}` },
3931
+ children: [
3932
+ /* @__PURE__ */ jsx(Flex, { gap: "0", style: { borderBottom: `0.1vh solid ${alpha(warnColor, 0.18)}` }, children: TABS.map((tab) => {
3933
+ const active = tab.id === activeTab;
3934
+ const hovered = hoveredTab === tab.id;
3935
+ let bg = "transparent";
3936
+ if (active) bg = alpha(warnColor, 0.12);
3937
+ else if (hovered) bg = alpha(warnColor, 0.08);
3938
+ return /* @__PURE__ */ jsx(
3939
+ "button",
3940
+ {
3941
+ onClick: (e) => {
3942
+ e.stopPropagation();
3943
+ setActiveTab(tab.id);
3944
+ },
3945
+ onMouseEnter: () => setHoveredTab(tab.id),
3946
+ onMouseLeave: () => setHoveredTab((h) => h === tab.id ? null : h),
3947
+ style: {
3948
+ flex: 1,
3949
+ background: bg,
3950
+ border: "none",
3951
+ borderBottom: active ? `0.2vh solid ${warnColor}` : "0.2vh solid transparent",
3952
+ padding: "0.3vh 1vh",
3953
+ cursor: active ? "default" : "pointer",
3954
+ color: active ? warnColor : "rgba(255,255,255,0.5)",
3955
+ fontFamily: "Akrobat Bold",
3956
+ fontSize: "var(--mantine-font-size-xxs)",
3957
+ letterSpacing: "0.07em",
3958
+ textTransform: "uppercase",
3959
+ transition: "background 0.12s"
3960
+ },
3961
+ children: tab.label
3962
+ },
3963
+ tab.id
3964
+ );
3965
+ }) }),
3966
+ /* @__PURE__ */ jsx(
3967
+ CodeView,
3968
+ {
3969
+ code: audit.snippets[activeTab] ?? "",
3970
+ copied: copied === activeTab,
3971
+ onCopy: (e) => {
3972
+ e.stopPropagation();
3973
+ handleCopy(activeTab);
3974
+ },
3975
+ warnColor
3976
+ }
3977
+ )
3978
+ ]
3979
+ },
3980
+ "expanded"
3981
+ ) })
3982
+ ]
3983
+ }
3984
+ );
3985
+ }
3986
+ function CodeView({
3987
+ code,
3988
+ copied,
3989
+ onCopy,
3990
+ warnColor
3991
+ }) {
3992
+ const theme2 = useMantineTheme();
3993
+ const [hovered, setHovered] = useState(false);
3994
+ const lines = code === "" ? [""] : code.split("\n");
3995
+ const lineNumWidth = String(lines.length).length;
3996
+ const copyBg = copied ? alpha("#22c55e", 0.15) : hovered ? alpha(warnColor, 0.18) : alpha(warnColor, 0.1);
3997
+ return /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
3998
+ /* @__PURE__ */ jsxs(
3999
+ "button",
4000
+ {
4001
+ onClick: onCopy,
4002
+ onMouseEnter: () => setHovered(true),
4003
+ onMouseLeave: () => setHovered(false),
4004
+ style: {
4005
+ position: "absolute",
4006
+ top: "0.6vh",
4007
+ right: "0.8vh",
4008
+ zIndex: 2,
4009
+ background: copyBg,
4010
+ border: `0.1vh solid ${alpha(copied ? "#22c55e" : warnColor, 0.35)}`,
4011
+ borderRadius: theme2.radius.xs,
4012
+ padding: "0.4vh 0.7vh",
4013
+ cursor: "pointer",
4014
+ display: "flex",
4015
+ alignItems: "center",
4016
+ gap: "0.4vh",
4017
+ transition: "background 0.12s"
4018
+ },
4019
+ children: [
4020
+ copied ? /* @__PURE__ */ jsx(Check, { size: "1.4vh", color: "#22c55e" }) : /* @__PURE__ */ jsx(Copy, { size: "1.4vh", color: warnColor }),
4021
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: copied ? "#22c55e" : warnColor, children: copied ? "Copied" : "Copy" })
4022
+ ]
4023
+ }
4024
+ ),
4025
+ /* @__PURE__ */ jsx("div", { style: {
4026
+ background: alpha(theme2.colors.dark[9], 0.6),
4027
+ maxHeight: "40vh",
4028
+ overflowY: "auto",
4029
+ overflowX: "auto",
4030
+ padding: "0.6vh 0"
4031
+ }, 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: [
4032
+ /* @__PURE__ */ jsx("td", { style: {
4033
+ width: `${lineNumWidth + 2}ch`,
4034
+ textAlign: "right",
4035
+ padding: "0 0.8vh 0 1vh",
4036
+ color: "rgba(255,255,255,0.25)",
4037
+ userSelect: "none",
4038
+ whiteSpace: "nowrap",
4039
+ verticalAlign: "top"
4040
+ }, children: i + 1 }),
4041
+ /* @__PURE__ */ jsx("td", { style: {
4042
+ padding: "0 1vh",
4043
+ color: "rgba(255,255,255,0.85)",
4044
+ whiteSpace: "pre",
4045
+ verticalAlign: "top"
4046
+ }, children: line || "\u200B" })
4047
+ ] }, i)) }) }) })
4048
+ ] });
4049
+ }
3810
4050
  function getNested(obj, path) {
3811
4051
  return path.split(".").reduce((acc, key) => acc ? acc[key] : void 0, obj);
3812
4052
  }
@@ -4533,7 +4773,8 @@ function ConfigPanelInner({
4533
4773
  resetConfirmText,
4534
4774
  defaultConfig,
4535
4775
  width,
4536
- height
4776
+ height,
4777
+ suppressMissingItemsBanner
4537
4778
  }) {
4538
4779
  const { updateConfig, resetConfig, getHistory } = getScriptConfigInstance();
4539
4780
  const form = useForm();
@@ -4756,18 +4997,21 @@ function ConfigPanelInner({
4756
4997
  ] })
4757
4998
  ] })
4758
4999
  ] }),
4759
- /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
4760
- motion.div,
4761
- {
4762
- initial: firstMountRef.current ? (firstMountRef.current = false, false) : { opacity: 0, y: 4 },
4763
- animate: { opacity: 1, y: 0 },
4764
- exit: { opacity: 0, y: -4 },
4765
- transition: { duration: 0.15 },
4766
- style: { flex: 1, display: "flex", flexDirection: "column", overflowY: "auto" },
4767
- children: children(activeTab)
4768
- },
4769
- activeTab
4770
- ) })
5000
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: [
5001
+ !suppressMissingItemsBanner && /* @__PURE__ */ jsx(MissingItemsBanner, {}),
5002
+ /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
5003
+ motion.div,
5004
+ {
5005
+ initial: firstMountRef.current ? (firstMountRef.current = false, false) : { opacity: 0, y: 4 },
5006
+ animate: { opacity: 1, y: 0 },
5007
+ exit: { opacity: 0, y: -4 },
5008
+ transition: { duration: 0.15 },
5009
+ style: { flex: 1, display: "flex", flexDirection: "column", overflowY: "auto" },
5010
+ children: children(activeTab)
5011
+ },
5012
+ activeTab
5013
+ ) })
5014
+ ] })
4771
5015
  ]
4772
5016
  }
4773
5017
  )
@@ -4809,6 +5053,7 @@ function ConfigPanel(props) {
4809
5053
  if (result?.success) {
4810
5054
  form.reinitialize(cloneConfig(form.values));
4811
5055
  configPanelQueryClient.invalidateQueries({ queryKey: ["scriptConfigHistory"] });
5056
+ useMissingItemsAudit.getState().refresh();
4812
5057
  notifications.show({
4813
5058
  color: "green",
4814
5059
  title: locale("ConfigSaveSuccessTitle"),
@@ -4846,6 +5091,7 @@ function ConfigPanel(props) {
4846
5091
  }
4847
5092
  ) });
4848
5093
  }
5094
+ var MISSING_COLOR = "#f59e0b";
4849
5095
  function LazyImage({ src, style }) {
4850
5096
  const [visible, setVisible] = useState(false);
4851
5097
  const ref = useRef(null);
@@ -4863,14 +5109,19 @@ function LazyImage({ src, style }) {
4863
5109
  }
4864
5110
  function SelectItem(props) {
4865
5111
  const invItems = useItems();
5112
+ const isMissing = !!props.value && !invItems[props.value];
4866
5113
  const formattedItems = useMemo(() => {
4867
5114
  const seen = /* @__PURE__ */ new Set();
4868
- return useItemsList(props.excludeItemNames ?? []).filter((item) => {
5115
+ const list = useItemsList(props.excludeItemNames ?? []).filter((item) => {
4869
5116
  if (seen.has(item.name)) return false;
4870
5117
  seen.add(item.name);
4871
5118
  return true;
4872
5119
  }).map((item) => ({ value: item.name, label: item.label, image: item.image }));
4873
- }, [invItems, props.excludeItemNames]);
5120
+ if (isMissing) {
5121
+ list.unshift({ value: props.value, label: props.value, image: "" });
5122
+ }
5123
+ return list;
5124
+ }, [invItems, props.excludeItemNames, props.value, isMissing]);
4874
5125
  return /* @__PURE__ */ jsx(
4875
5126
  Select,
4876
5127
  {
@@ -4885,10 +5136,11 @@ function SelectItem(props) {
4885
5136
  data: formattedItems,
4886
5137
  allowDeselect: false,
4887
5138
  searchable: true,
5139
+ styles: isMissing ? { input: { color: MISSING_COLOR } } : void 0,
4888
5140
  comboboxProps: { withinPortal: true, zIndex: 2e3 },
4889
5141
  leftSectionWidth: "4vh",
4890
5142
  leftSectionPointerEvents: "none",
4891
- leftSection: props.value ? /* @__PURE__ */ jsx(
5143
+ 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(
4892
5144
  Image$1,
4893
5145
  {
4894
5146
  fallbackSrc: "/placeholder.png",
@@ -4899,19 +5151,37 @@ function SelectItem(props) {
4899
5151
  }
4900
5152
  ) : null,
4901
5153
  nothingFoundMessage: locale("NoItemsFound"),
4902
- renderOption: (item) => /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "xs", w: "100%", children: [
4903
- /* @__PURE__ */ jsx(
4904
- LazyImage,
4905
- {
4906
- src: invItems[item.option.value]?.image || "",
4907
- style: { aspectRatio: "1 / 1" }
4908
- }
4909
- ),
4910
- /* @__PURE__ */ jsxs(Flex, { direction: "column", children: [
4911
- /* @__PURE__ */ jsx(Text, { size: "sm", children: item.option.label }),
4912
- /* @__PURE__ */ jsx(Text, { size: "xxs", c: "dimmed", children: item.option.value })
4913
- ] })
4914
- ] })
5154
+ renderOption: (item) => {
5155
+ const optionMissing = !invItems[item.option.value] && item.option.value === props.value;
5156
+ if (optionMissing) {
5157
+ return /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "xs", w: "100%", children: [
5158
+ /* @__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 }) }),
5159
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", style: { flex: 1, minWidth: 0 }, children: [
5160
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: MISSING_COLOR, style: { fontFamily: "monospace" }, children: item.option.value }),
5161
+ /* @__PURE__ */ jsx(Text, { size: "xxs", c: "dimmed", children: locale("ItemNotInInventory") })
5162
+ ] }),
5163
+ /* @__PURE__ */ jsx("div", { style: {
5164
+ background: "rgba(245,158,11,0.12)",
5165
+ border: `0.1vh solid ${MISSING_COLOR}59`,
5166
+ borderRadius: "0.3vh",
5167
+ padding: "0.1vh 0.6vh"
5168
+ }, children: /* @__PURE__ */ jsx(Text, { size: "xxs", c: MISSING_COLOR, ff: "Akrobat Bold", tt: "uppercase", lts: "0.06em", children: locale("Missing") }) })
5169
+ ] });
5170
+ }
5171
+ return /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "xs", w: "100%", children: [
5172
+ /* @__PURE__ */ jsx(
5173
+ LazyImage,
5174
+ {
5175
+ src: invItems[item.option.value]?.image || "",
5176
+ style: { aspectRatio: "1 / 1" }
5177
+ }
5178
+ ),
5179
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", children: [
5180
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: item.option.label }),
5181
+ /* @__PURE__ */ jsx(Text, { size: "xxs", c: "dimmed", children: item.option.value })
5182
+ ] })
5183
+ ] });
5184
+ }
4915
5185
  }
4916
5186
  );
4917
5187
  }
@@ -6026,6 +6296,6 @@ function DirkProvider({ children, overideResourceName, themeOverride }) {
6026
6296
  return /* @__PURE__ */ jsx(MantineProvider, { theme: mergedTheme, defaultColorScheme: "dark", children: /* @__PURE__ */ jsx(DirkErrorBoundary, { children: content }) });
6027
6297
  }
6028
6298
 
6029
- export { AdminPageTitle, AsyncSaveButton, BlipColorSelect, BlipDisplaySelect, BlipIconSelect, BorderedIcon, ConfigPanel, ConfirmModal, ControlMultiSelect, ControlSelect, Counter, DirkProvider, 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, Modal, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PositionPicker, PromptModal, SegmentedControl, SegmentedProgress, SelectItem, TestBed, Title, TornEdgeSVGFilter, Vector4DeleteButton, Vector4Display, 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, useModal, useModalActions, useNavigation, useNavigationStore, useNuiEvent, useProfanityStore, useSettings, useTornEdges };
6299
+ export { AdminPageTitle, AsyncSaveButton, BlipColorSelect, BlipDisplaySelect, BlipIconSelect, BorderedIcon, ConfigPanel, ConfirmModal, ControlMultiSelect, ControlSelect, Counter, DirkProvider, 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, SegmentedControl, SegmentedProgress, SelectItem, TestBed, Title, TornEdgeSVGFilter, Vector4DeleteButton, Vector4Display, 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 };
6030
6300
  //# sourceMappingURL=index.js.map
6031
6301
  //# sourceMappingURL=index.js.map