dirk-cfx-react 1.1.62 → 1.1.65

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.
@@ -6,9 +6,9 @@ var react = require('react');
6
6
  var zustand = require('zustand');
7
7
  var reactFontawesome = require('@fortawesome/react-fontawesome');
8
8
  var framerMotion = require('framer-motion');
9
+ var lucideReact = require('lucide-react');
9
10
  var clickSoundUrl = require('../click_sound-PNCRRTM4.mp3');
10
11
  var hoverSoundUrl = require('../hover_sound-NBUA222C.mp3');
11
- var lucideReact = require('lucide-react');
12
12
  var reactQuery = require('@tanstack/react-query');
13
13
 
14
14
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -1064,6 +1064,31 @@ function BlipColorSelect({ value, onChange, label = "Blip Color", size = "xs", .
1064
1064
  }
1065
1065
  );
1066
1066
  }
1067
+ var BLIP_DISPLAY_DATA = [
1068
+ { value: "2", label: "2 \u2014 Main map + minimap (selectable)" },
1069
+ { value: "3", label: "3 \u2014 Main map only (selectable)" },
1070
+ { value: "4", label: "4 \u2014 Main map only (selectable)" },
1071
+ { value: "5", label: "5 \u2014 Minimap only" },
1072
+ { value: "6", label: "6 \u2014 Main map + minimap (selectable)" },
1073
+ { value: "8", label: "8 \u2014 Main map + minimap (not selectable)" },
1074
+ { value: "9", label: "9 \u2014 Minimap only" },
1075
+ { value: "10", label: "10 \u2014 Main map + minimap (not selectable)" }
1076
+ ];
1077
+ function BlipDisplaySelect({ value, onChange, label = "Blip Display", size = "xs", ...rest }) {
1078
+ return /* @__PURE__ */ jsxRuntime.jsx(
1079
+ core.Select,
1080
+ {
1081
+ label,
1082
+ size,
1083
+ ...rest,
1084
+ data: BLIP_DISPLAY_DATA,
1085
+ value: value != null ? String(value) : null,
1086
+ onChange: (val) => val != null && onChange(Number(val)),
1087
+ allowDeselect: false,
1088
+ maxDropdownHeight: 300
1089
+ }
1090
+ );
1091
+ }
1067
1092
 
1068
1093
  // src/utils/colorWithAlpha.ts
1069
1094
  var colorNames = {
@@ -1210,11 +1235,11 @@ var colorNames = {
1210
1235
  Yellow: { r: 255, g: 255, b: 0 },
1211
1236
  YellowGreen: { r: 154, g: 205, b: 50 }
1212
1237
  };
1213
- function colorWithAlpha(color, alpha8) {
1238
+ function colorWithAlpha(color, alpha9) {
1214
1239
  const lowerCasedColor = color.toLowerCase();
1215
1240
  if (colorNames[lowerCasedColor]) {
1216
1241
  const rgb = colorNames[lowerCasedColor];
1217
- return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha8})`;
1242
+ return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha9})`;
1218
1243
  }
1219
1244
  if (/^#([A-Fa-f0-9]{6})$/.test(color)) {
1220
1245
  const hex = color.slice(1);
@@ -1222,12 +1247,12 @@ function colorWithAlpha(color, alpha8) {
1222
1247
  const r = bigint >> 16 & 255;
1223
1248
  const g = bigint >> 8 & 255;
1224
1249
  const b = bigint & 255;
1225
- return `rgba(${r}, ${g}, ${b}, ${alpha8})`;
1250
+ return `rgba(${r}, ${g}, ${b}, ${alpha9})`;
1226
1251
  }
1227
1252
  if (/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/.test(color)) {
1228
1253
  const result = color.match(/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/);
1229
1254
  if (result) {
1230
- return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${alpha8})`;
1255
+ return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${alpha9})`;
1231
1256
  }
1232
1257
  }
1233
1258
  return color;
@@ -1274,13 +1299,24 @@ async function fetchNui(eventName, data, mockData) {
1274
1299
  }
1275
1300
  const overrideResourceName = useSettings.getState().overideResourceName;
1276
1301
  const resourceName = window.GetParentResourceName ? window.GetParentResourceName() : overrideResourceName ? overrideResourceName : "dirk-cfx-react";
1277
- const resp = await fetch(`https://${resourceName}/${eventName}`, options);
1278
- return await resp.json();
1302
+ try {
1303
+ const resp = await fetch(`https://${resourceName}/${eventName}`, options);
1304
+ return await resp.json();
1305
+ } catch {
1306
+ return mockData ?? {};
1307
+ }
1279
1308
  }
1280
1309
  async function registerInitialFetch(eventName, data, mockData) {
1281
1310
  const fetcher = () => fetchNui(eventName, data, mockData);
1282
1311
  return fetcher();
1283
1312
  }
1313
+ var reportedMissing = /* @__PURE__ */ new Set();
1314
+ function reportMissingLocale(key) {
1315
+ if (!key || reportedMissing.has(key)) return;
1316
+ reportedMissing.add(key);
1317
+ fetchNui("REPORT_MISSING_LOCALE", { key }).catch(() => {
1318
+ });
1319
+ }
1284
1320
  var localeStore = zustand.create((set, get) => {
1285
1321
  return {
1286
1322
  locales: {
@@ -1288,6 +1324,7 @@ var localeStore = zustand.create((set, get) => {
1288
1324
  },
1289
1325
  locale: (key, ...args) => {
1290
1326
  const exists = get().locales[key];
1327
+ if (!exists) reportMissingLocale(key);
1291
1328
  let translation = exists || key;
1292
1329
  if (args.length) {
1293
1330
  translation = translation.replace(/%s/g, () => String(args.shift() || ""));
@@ -1301,6 +1338,14 @@ registerInitialFetch("GET_LOCALES", void 0).then((data) => {
1301
1338
  localeStore.setState({ locales: data });
1302
1339
  }).catch(() => {
1303
1340
  });
1341
+ if (typeof window !== "undefined") {
1342
+ window.addEventListener("message", (event) => {
1343
+ const msg = event.data;
1344
+ if (!msg || msg.action !== "UPDATE_DIRK_LIB_LOCALES") return;
1345
+ if (!msg.data || typeof msg.data !== "object") return;
1346
+ localeStore.setState({ locales: msg.data });
1347
+ });
1348
+ }
1304
1349
  var useItems = zustand.create(() => ({}));
1305
1350
  var useItemsList = (excludeItemNames = []) => {
1306
1351
  const excludeSet = new Set(excludeItemNames);
@@ -1940,8 +1985,8 @@ function InputContainer(props) {
1940
1985
  (props.title || props.description) && /* @__PURE__ */ jsxRuntime.jsxs(
1941
1986
  core.Flex,
1942
1987
  {
1943
- direction: "column",
1944
- gap: "xxs",
1988
+ align: "center",
1989
+ flex: 1,
1945
1990
  p: props.p == "0" ? "sm" : 0,
1946
1991
  children: [
1947
1992
  props.title && /* @__PURE__ */ jsxRuntime.jsx(
@@ -1958,12 +2003,26 @@ function InputContainer(props) {
1958
2003
  }
1959
2004
  ),
1960
2005
  props.description && /* @__PURE__ */ jsxRuntime.jsx(
1961
- core.Text,
2006
+ core.Tooltip,
1962
2007
  {
1963
- size: "xs",
1964
- c: "rgba(255, 255, 255, 0.8)",
1965
- fw: 400,
1966
- children: props.description
2008
+ label: props.description,
2009
+ position: "top-end",
2010
+ withArrow: true,
2011
+ multiline: true,
2012
+ maw: "22vh",
2013
+ styles: {
2014
+ tooltip: {
2015
+ background: core.alpha(theme.colors.dark[7], 0.95),
2016
+ border: `0.1vh solid rgba(255,255,255,0.1)`,
2017
+ color: "rgba(255,255,255,0.75)",
2018
+ fontFamily: "Akrobat Bold",
2019
+ fontSize: "1.3vh",
2020
+ lineHeight: 1.3,
2021
+ padding: "0.6vh 0.8vh",
2022
+ letterSpacing: "0.03em"
2023
+ }
2024
+ },
2025
+ children: /* @__PURE__ */ jsxRuntime.jsx(core.Flex, { align: "center", justify: "center", style: { marginLeft: "auto", cursor: "help" }, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { size: "1.6vh", color: core.alpha(theme.colors[theme.primaryColor][5], 0.45) }) })
1967
2026
  }
1968
2027
  )
1969
2028
  ]
@@ -1980,13 +2039,7 @@ function InputContainer(props) {
1980
2039
  children: props.error
1981
2040
  }
1982
2041
  ),
1983
- /* @__PURE__ */ jsxRuntime.jsx(
1984
- core.Flex,
1985
- {
1986
- ml: "auto",
1987
- children: props.rightSection
1988
- }
1989
- )
2042
+ props.rightSection && /* @__PURE__ */ jsxRuntime.jsx(core.Flex, { children: props.rightSection })
1990
2043
  ]
1991
2044
  }
1992
2045
  ),
@@ -3995,6 +4048,219 @@ function SelectItem(props) {
3995
4048
  }
3996
4049
  );
3997
4050
  }
4051
+ var ZERO = { x: 0, y: 0, z: 0, w: 0 };
4052
+ function PositionPicker(props) {
4053
+ const {
4054
+ label,
4055
+ value,
4056
+ onChange,
4057
+ relativeTo,
4058
+ fetchEvent = "GET_POSITION",
4059
+ previewEvent = "PREVIEW_POSITION",
4060
+ stopPreviewEvent = "STOP_PREVIEW_POSITION",
4061
+ description,
4062
+ showHeading = true
4063
+ } = props;
4064
+ const theme = core.useMantineTheme();
4065
+ const color = theme.colors[theme.primaryColor][5];
4066
+ const [previewing, setPreviewing] = react.useState(false);
4067
+ const previewingRef = react.useRef(false);
4068
+ react.useEffect(() => {
4069
+ return () => {
4070
+ if (previewingRef.current) {
4071
+ fetchNui(stopPreviewEvent, { relativeTo }).catch(() => {
4072
+ });
4073
+ }
4074
+ };
4075
+ }, [stopPreviewEvent, relativeTo]);
4076
+ const set = (key, val) => {
4077
+ const next = { ...value, [key]: val };
4078
+ onChange(next);
4079
+ if (previewingRef.current) {
4080
+ fetchNui(previewEvent, { value: next, relativeTo }).catch(() => {
4081
+ });
4082
+ }
4083
+ };
4084
+ const grab = async () => {
4085
+ try {
4086
+ const resp = await fetchNui(fetchEvent, { relativeTo }, value);
4087
+ if (resp && typeof resp === "object") {
4088
+ const next = {
4089
+ x: Number(resp.x ?? 0),
4090
+ y: Number(resp.y ?? 0),
4091
+ z: Number(resp.z ?? 0),
4092
+ w: Number(resp.w ?? 0)
4093
+ };
4094
+ onChange(next);
4095
+ if (previewingRef.current) {
4096
+ fetchNui(previewEvent, { value: next, relativeTo }).catch(() => {
4097
+ });
4098
+ }
4099
+ }
4100
+ } catch {
4101
+ }
4102
+ };
4103
+ const togglePreview = async () => {
4104
+ const nextState = !previewing;
4105
+ setPreviewing(nextState);
4106
+ previewingRef.current = nextState;
4107
+ if (nextState) {
4108
+ await fetchNui(previewEvent, { value, relativeTo }).catch(() => {
4109
+ });
4110
+ } else {
4111
+ await fetchNui(stopPreviewEvent, { relativeTo }).catch(() => {
4112
+ });
4113
+ }
4114
+ };
4115
+ const reset = () => {
4116
+ onChange({ ...ZERO });
4117
+ if (previewingRef.current) {
4118
+ fetchNui(previewEvent, { value: ZERO, relativeTo }).catch(() => {
4119
+ });
4120
+ }
4121
+ };
4122
+ const numberStyles = {
4123
+ input: { textAlign: "right", fontFamily: "monospace" }
4124
+ };
4125
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4126
+ core.Flex,
4127
+ {
4128
+ direction: "column",
4129
+ gap: "xxs",
4130
+ p: "xs",
4131
+ style: {
4132
+ background: core.alpha(theme.colors.dark[5], 0.35),
4133
+ border: "0.1vh solid rgba(255,255,255,0.05)",
4134
+ borderRadius: theme.radius.xs
4135
+ },
4136
+ children: [
4137
+ (label || description) && /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { justify: "space-between", align: "center", gap: "xs", children: [
4138
+ /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", gap: 0, style: { minWidth: 0 }, children: [
4139
+ label && /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "xxs", children: [
4140
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MapPin, { size: "1.4vh", color: core.alpha(color, 0.7) }),
4141
+ /* @__PURE__ */ jsxRuntime.jsx(
4142
+ core.Text,
4143
+ {
4144
+ ff: "Akrobat Bold",
4145
+ size: "xxs",
4146
+ tt: "uppercase",
4147
+ lts: "0.05em",
4148
+ c: "rgba(255,255,255,0.75)",
4149
+ children: locale(label)
4150
+ }
4151
+ ),
4152
+ relativeTo && /* @__PURE__ */ jsxRuntime.jsxs(core.Text, { ff: "Akrobat Bold", size: "xxs", c: core.alpha(color, 0.5), lts: "0.05em", children: [
4153
+ "\xB7 ",
4154
+ locale("RelativeTo"),
4155
+ " ",
4156
+ relativeTo
4157
+ ] })
4158
+ ] }),
4159
+ description && /* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", c: "dimmed", lh: 1.3, children: locale(description) })
4160
+ ] }),
4161
+ /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { gap: "xxs", style: { flexShrink: 0 }, children: [
4162
+ /* @__PURE__ */ jsxRuntime.jsx(PickerButton, { tooltip: locale("GrabMyPosition"), onClick: grab, color, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crosshair, { size: "1.4vh", color }) }),
4163
+ /* @__PURE__ */ jsxRuntime.jsx(
4164
+ PickerButton,
4165
+ {
4166
+ tooltip: previewing ? locale("StopPreview") : locale("PreviewInWorld"),
4167
+ onClick: togglePreview,
4168
+ color,
4169
+ active: previewing,
4170
+ children: previewing ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, { size: "1.4vh", color }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: "1.4vh", color: core.alpha(color, 0.7) })
4171
+ }
4172
+ ),
4173
+ /* @__PURE__ */ jsxRuntime.jsx(PickerButton, { tooltip: locale("Reset"), onClick: reset, color: "#ef4444", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { size: "1.4vh", color: "#ef4444" }) })
4174
+ ] })
4175
+ ] }),
4176
+ /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { gap: "xxs", children: [
4177
+ /* @__PURE__ */ jsxRuntime.jsx(
4178
+ core.NumberInput,
4179
+ {
4180
+ size: "xs",
4181
+ label: "X",
4182
+ value: value.x,
4183
+ onChange: (v) => set("x", Number(v)),
4184
+ decimalScale: 4,
4185
+ step: 0.1,
4186
+ style: { flex: 1 },
4187
+ styles: numberStyles
4188
+ }
4189
+ ),
4190
+ /* @__PURE__ */ jsxRuntime.jsx(
4191
+ core.NumberInput,
4192
+ {
4193
+ size: "xs",
4194
+ label: "Y",
4195
+ value: value.y,
4196
+ onChange: (v) => set("y", Number(v)),
4197
+ decimalScale: 4,
4198
+ step: 0.1,
4199
+ style: { flex: 1 },
4200
+ styles: numberStyles
4201
+ }
4202
+ ),
4203
+ /* @__PURE__ */ jsxRuntime.jsx(
4204
+ core.NumberInput,
4205
+ {
4206
+ size: "xs",
4207
+ label: "Z",
4208
+ value: value.z,
4209
+ onChange: (v) => set("z", Number(v)),
4210
+ decimalScale: 4,
4211
+ step: 0.1,
4212
+ style: { flex: 1 },
4213
+ styles: numberStyles
4214
+ }
4215
+ ),
4216
+ showHeading && /* @__PURE__ */ jsxRuntime.jsx(
4217
+ core.NumberInput,
4218
+ {
4219
+ size: "xs",
4220
+ label: "W",
4221
+ value: value.w,
4222
+ onChange: (v) => set("w", Number(v)),
4223
+ decimalScale: 2,
4224
+ step: 1,
4225
+ min: 0,
4226
+ max: 360,
4227
+ style: { flex: 1 },
4228
+ styles: numberStyles
4229
+ }
4230
+ )
4231
+ ] })
4232
+ ]
4233
+ }
4234
+ );
4235
+ }
4236
+ function PickerButton({
4237
+ children,
4238
+ onClick,
4239
+ tooltip,
4240
+ color,
4241
+ active
4242
+ }) {
4243
+ const theme = core.useMantineTheme();
4244
+ return /* @__PURE__ */ jsxRuntime.jsx(core.Tooltip, { label: tooltip, position: "top", withArrow: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4245
+ framerMotion.motion.button,
4246
+ {
4247
+ onClick,
4248
+ whileHover: { background: core.alpha(color, 0.18) },
4249
+ whileTap: { scale: 0.95 },
4250
+ style: {
4251
+ background: active ? core.alpha(color, 0.22) : core.alpha(color, 0.08),
4252
+ border: `0.1vh solid ${core.alpha(color, active ? 0.5 : 0.3)}`,
4253
+ borderRadius: theme.radius.xs,
4254
+ padding: "0.4vh 0.6vh",
4255
+ cursor: "pointer",
4256
+ display: "flex",
4257
+ alignItems: "center",
4258
+ justifyContent: "center"
4259
+ },
4260
+ children
4261
+ }
4262
+ ) });
4263
+ }
3998
4264
  var KeyBindContext = react.createContext(null);
3999
4265
  function useKeyBindContext() {
4000
4266
  const ctx = react.useContext(KeyBindContext);
@@ -4281,6 +4547,7 @@ function TestBed({
4281
4547
  exports.AdminPageTitle = AdminPageTitle;
4282
4548
  exports.AsyncSaveButton = AsyncSaveButton;
4283
4549
  exports.BlipColorSelect = BlipColorSelect;
4550
+ exports.BlipDisplaySelect = BlipDisplaySelect;
4284
4551
  exports.BlipIconSelect = BlipIconSelect;
4285
4552
  exports.BorderedIcon = BorderedIcon;
4286
4553
  exports.ConfigPanel = ConfigPanel;
@@ -4302,6 +4569,7 @@ exports.MotionText = MotionText;
4302
4569
  exports.NavBar = NavBar;
4303
4570
  exports.NavigationContext = NavigationContext;
4304
4571
  exports.NavigationProvider = NavigationProvider;
4572
+ exports.PositionPicker = PositionPicker;
4305
4573
  exports.PromptModal = PromptModal;
4306
4574
  exports.SegmentedControl = SegmentedControl;
4307
4575
  exports.SegmentedProgress = SegmentedProgress;