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.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- export { AdminPageTitle, AdminPageTitleProps, AsyncSaveButton, BlipColorSelect, BlipColorSelectProps, BlipIconSelect, BlipIconSelectProps, BorderedIcon, BorderedIconProps, ButtonProps, ConfigPanel, ConfigPanelProps, ConfirmModal, ConfirmModalProps, Counter, FiveMControls, FiveMKeyBindInput, FloatingParticles, FloatingParticlesProps, InfoBox, InfoBoxProps, InputContainer, InputContainerProps, LevelBanner, LevelPanel, Modal, ModalContext, ModalProps, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavItem, NavigationContext, NavigationProvider, NavigationStore, ParticleState, ProgressProps, Prompt, PromptButton, PromptModal, SegmentProps, SegmentedControl, SegmentedControlProps, SegmentedProgress, SelectItem, SelectItemProps, StoreModalProps, TestBed, TestBedItem, TestBedProps, Title, TitleProps, 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, Counter, FiveMControls, FiveMKeyBindInput, FloatingParticles, FloatingParticlesProps, 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, Vector4Value, useModal, useModalActions, useNavigation, useNavigationStore } from './components/index.cjs';
2
2
  export { INPUT_MAPPER_KEYS_BY_PRIMARY, INPUT_MAPPER_PRIMARY_OPTIONS, InitialFetch, InternalEvent, InventoryItem, InventoryItems, SettingsState, SkillSettings, UploadImageProps, colorWithAlpha, copyToClipboard, createSkill, extractDefaults, fetchLuaTable, fetchNui, gameToMap, getImageShape, getItemImageUrl, initialFetches, internalEvent, isEnvBrowser, isProfanity, latPr100, locale, localeStore, mapCenter, mapToGame, noop, numberToRoman, openLink, registerInitialFetch, registerInitialLuaTableFetch, runFetches, splitFAString, updatePresignedURL, uploadImage, useAutoFetcher, 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, BlipIconSelect, BlipIconSelectProps, BorderedIcon, BorderedIconProps, ButtonProps, ConfigPanel, ConfigPanelProps, ConfirmModal, ConfirmModalProps, Counter, FiveMControls, FiveMKeyBindInput, FloatingParticles, FloatingParticlesProps, InfoBox, InfoBoxProps, InputContainer, InputContainerProps, LevelBanner, LevelPanel, Modal, ModalContext, ModalProps, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavItem, NavigationContext, NavigationProvider, NavigationStore, ParticleState, ProgressProps, Prompt, PromptButton, PromptModal, SegmentProps, SegmentedControl, SegmentedControlProps, SegmentedProgress, SelectItem, SelectItemProps, StoreModalProps, TestBed, TestBedItem, TestBedProps, Title, TitleProps, 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, Counter, FiveMControls, FiveMKeyBindInput, FloatingParticles, FloatingParticlesProps, 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, Vector4Value, useModal, useModalActions, useNavigation, useNavigationStore } from './components/index.js';
2
2
  export { INPUT_MAPPER_KEYS_BY_PRIMARY, INPUT_MAPPER_PRIMARY_OPTIONS, InitialFetch, InternalEvent, InventoryItem, InventoryItems, SettingsState, SkillSettings, UploadImageProps, colorWithAlpha, copyToClipboard, createSkill, extractDefaults, fetchLuaTable, fetchNui, gameToMap, getImageShape, getItemImageUrl, initialFetches, internalEvent, isEnvBrowser, isProfanity, latPr100, locale, localeStore, mapCenter, mapToGame, noop, numberToRoman, openLink, registerInitialFetch, registerInitialLuaTableFetch, runFetches, splitFAString, updatePresignedURL, uploadImage, useAutoFetcher, 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,13 +1,13 @@
1
- import { Flex, Text, Image as Image$1, createTheme, Box, Stack, Title as Title$1, Code, TextInput, Select, useMantineTheme, alpha, Progress, RingProgress, Portal, Button, Loader, ActionIcon, MantineProvider, BackgroundImage, Group, JsonInput } from '@mantine/core';
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, Loader, ActionIcon, MantineProvider, BackgroundImage, Group, JsonInput } from '@mantine/core';
2
2
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
  import React5, { createContext, useContext, useEffect, useRef, useState, 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
9
  import clickSoundUrl from './click_sound-PNCRRTM4.mp3';
9
10
  import hoverSoundUrl from './hover_sound-NBUA222C.mp3';
10
- import { X, AlertTriangle, Trash2, Check, FlaskConical, ChevronUp, ChevronDown, ArrowLeft, Undo2, Redo2, Save, History, XCircle, Code2, RotateCcw, Search, Filter, User } from 'lucide-react';
11
11
  import { QueryClient, QueryClientProvider, useInfiniteQuery } from '@tanstack/react-query';
12
12
  import '@mantine/core/styles.css';
13
13
  import '@mantine/notifications/styles.css';
@@ -1070,6 +1070,31 @@ function BlipColorSelect({ value, onChange, label: label2 = "Blip Color", size =
1070
1070
  }
1071
1071
  );
1072
1072
  }
1073
+ var BLIP_DISPLAY_DATA = [
1074
+ { value: "2", label: "2 \u2014 Main map + minimap (selectable)" },
1075
+ { value: "3", label: "3 \u2014 Main map only (selectable)" },
1076
+ { value: "4", label: "4 \u2014 Main map only (selectable)" },
1077
+ { value: "5", label: "5 \u2014 Minimap only" },
1078
+ { value: "6", label: "6 \u2014 Main map + minimap (selectable)" },
1079
+ { value: "8", label: "8 \u2014 Main map + minimap (not selectable)" },
1080
+ { value: "9", label: "9 \u2014 Minimap only" },
1081
+ { value: "10", label: "10 \u2014 Main map + minimap (not selectable)" }
1082
+ ];
1083
+ function BlipDisplaySelect({ value, onChange, label: label2 = "Blip Display", size = "xs", ...rest }) {
1084
+ return /* @__PURE__ */ jsx(
1085
+ Select,
1086
+ {
1087
+ label: label2,
1088
+ size,
1089
+ ...rest,
1090
+ data: BLIP_DISPLAY_DATA,
1091
+ value: value != null ? String(value) : null,
1092
+ onChange: (val) => val != null && onChange(Number(val)),
1093
+ allowDeselect: false,
1094
+ maxDropdownHeight: 300
1095
+ }
1096
+ );
1097
+ }
1073
1098
 
1074
1099
  // src/utils/colorWithAlpha.ts
1075
1100
  var colorNames = {
@@ -1216,11 +1241,11 @@ var colorNames = {
1216
1241
  Yellow: { r: 255, g: 255, b: 0 },
1217
1242
  YellowGreen: { r: 154, g: 205, b: 50 }
1218
1243
  };
1219
- function colorWithAlpha(color, alpha8) {
1244
+ function colorWithAlpha(color, alpha9) {
1220
1245
  const lowerCasedColor = color.toLowerCase();
1221
1246
  if (colorNames[lowerCasedColor]) {
1222
1247
  const rgb = colorNames[lowerCasedColor];
1223
- return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha8})`;
1248
+ return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha9})`;
1224
1249
  }
1225
1250
  if (/^#([A-Fa-f0-9]{6})$/.test(color)) {
1226
1251
  const hex = color.slice(1);
@@ -1228,12 +1253,12 @@ function colorWithAlpha(color, alpha8) {
1228
1253
  const r = bigint >> 16 & 255;
1229
1254
  const g = bigint >> 8 & 255;
1230
1255
  const b = bigint & 255;
1231
- return `rgba(${r}, ${g}, ${b}, ${alpha8})`;
1256
+ return `rgba(${r}, ${g}, ${b}, ${alpha9})`;
1232
1257
  }
1233
1258
  if (/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/.test(color)) {
1234
1259
  const result = color.match(/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/);
1235
1260
  if (result) {
1236
- return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${alpha8})`;
1261
+ return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${alpha9})`;
1237
1262
  }
1238
1263
  }
1239
1264
  return color;
@@ -1306,8 +1331,12 @@ async function fetchNui(eventName, data, mockData) {
1306
1331
  }
1307
1332
  const overrideResourceName = useSettings.getState().overideResourceName;
1308
1333
  const resourceName = window.GetParentResourceName ? window.GetParentResourceName() : overrideResourceName ? overrideResourceName : "dirk-cfx-react";
1309
- const resp = await fetch(`https://${resourceName}/${eventName}`, options);
1310
- return await resp.json();
1334
+ try {
1335
+ const resp = await fetch(`https://${resourceName}/${eventName}`, options);
1336
+ return await resp.json();
1337
+ } catch {
1338
+ return mockData ?? {};
1339
+ }
1311
1340
  }
1312
1341
  var initialFetches = {};
1313
1342
  async function registerInitialFetch(eventName, data, mockData) {
@@ -1354,6 +1383,13 @@ var internalEvent = (events, timer = 1e3) => {
1354
1383
  }
1355
1384
  }
1356
1385
  };
1386
+ var reportedMissing = /* @__PURE__ */ new Set();
1387
+ function reportMissingLocale(key) {
1388
+ if (!key || reportedMissing.has(key)) return;
1389
+ reportedMissing.add(key);
1390
+ fetchNui("REPORT_MISSING_LOCALE", { key }).catch(() => {
1391
+ });
1392
+ }
1357
1393
  var localeStore = create((set, get) => {
1358
1394
  return {
1359
1395
  locales: {
@@ -1361,6 +1397,7 @@ var localeStore = create((set, get) => {
1361
1397
  },
1362
1398
  locale: (key, ...args) => {
1363
1399
  const exists = get().locales[key];
1400
+ if (!exists) reportMissingLocale(key);
1364
1401
  let translation = exists || key;
1365
1402
  if (args.length) {
1366
1403
  translation = translation.replace(/%s/g, () => String(args.shift() || ""));
@@ -1374,6 +1411,14 @@ registerInitialFetch("GET_LOCALES", void 0).then((data) => {
1374
1411
  localeStore.setState({ locales: data });
1375
1412
  }).catch(() => {
1376
1413
  });
1414
+ if (typeof window !== "undefined") {
1415
+ window.addEventListener("message", (event) => {
1416
+ const msg = event.data;
1417
+ if (!msg || msg.action !== "UPDATE_DIRK_LIB_LOCALES") return;
1418
+ if (!msg.data || typeof msg.data !== "object") return;
1419
+ localeStore.setState({ locales: msg.data });
1420
+ });
1421
+ }
1377
1422
 
1378
1423
  // src/utils/map.ts
1379
1424
  var mapCenter = [-119.43, 58.84];
@@ -2536,8 +2581,8 @@ function InputContainer(props) {
2536
2581
  (props.title || props.description) && /* @__PURE__ */ jsxs(
2537
2582
  Flex,
2538
2583
  {
2539
- direction: "column",
2540
- gap: "xxs",
2584
+ align: "center",
2585
+ flex: 1,
2541
2586
  p: props.p == "0" ? "sm" : 0,
2542
2587
  children: [
2543
2588
  props.title && /* @__PURE__ */ jsx(
@@ -2554,12 +2599,26 @@ function InputContainer(props) {
2554
2599
  }
2555
2600
  ),
2556
2601
  props.description && /* @__PURE__ */ jsx(
2557
- Text,
2602
+ Tooltip,
2558
2603
  {
2559
- size: "xs",
2560
- c: "rgba(255, 255, 255, 0.8)",
2561
- fw: 400,
2562
- children: props.description
2604
+ label: props.description,
2605
+ position: "top-end",
2606
+ withArrow: true,
2607
+ multiline: true,
2608
+ maw: "22vh",
2609
+ styles: {
2610
+ tooltip: {
2611
+ background: alpha(theme2.colors.dark[7], 0.95),
2612
+ border: `0.1vh solid rgba(255,255,255,0.1)`,
2613
+ color: "rgba(255,255,255,0.75)",
2614
+ fontFamily: "Akrobat Bold",
2615
+ fontSize: "1.3vh",
2616
+ lineHeight: 1.3,
2617
+ padding: "0.6vh 0.8vh",
2618
+ letterSpacing: "0.03em"
2619
+ }
2620
+ },
2621
+ children: /* @__PURE__ */ jsx(Flex, { align: "center", justify: "center", style: { marginLeft: "auto", cursor: "help" }, children: /* @__PURE__ */ jsx(Info, { size: "1.6vh", color: alpha(theme2.colors[theme2.primaryColor][5], 0.45) }) })
2563
2622
  }
2564
2623
  )
2565
2624
  ]
@@ -2576,13 +2635,7 @@ function InputContainer(props) {
2576
2635
  children: props.error
2577
2636
  }
2578
2637
  ),
2579
- /* @__PURE__ */ jsx(
2580
- Flex,
2581
- {
2582
- ml: "auto",
2583
- children: props.rightSection
2584
- }
2585
- )
2638
+ props.rightSection && /* @__PURE__ */ jsx(Flex, { children: props.rightSection })
2586
2639
  ]
2587
2640
  }
2588
2641
  ),
@@ -4715,6 +4768,219 @@ function SelectItem(props) {
4715
4768
  }
4716
4769
  );
4717
4770
  }
4771
+ var ZERO = { x: 0, y: 0, z: 0, w: 0 };
4772
+ function PositionPicker(props) {
4773
+ const {
4774
+ label: label2,
4775
+ value,
4776
+ onChange,
4777
+ relativeTo,
4778
+ fetchEvent = "GET_POSITION",
4779
+ previewEvent = "PREVIEW_POSITION",
4780
+ stopPreviewEvent = "STOP_PREVIEW_POSITION",
4781
+ description: description2,
4782
+ showHeading = true
4783
+ } = props;
4784
+ const theme2 = useMantineTheme();
4785
+ const color = theme2.colors[theme2.primaryColor][5];
4786
+ const [previewing, setPreviewing] = useState(false);
4787
+ const previewingRef = useRef(false);
4788
+ useEffect(() => {
4789
+ return () => {
4790
+ if (previewingRef.current) {
4791
+ fetchNui(stopPreviewEvent, { relativeTo }).catch(() => {
4792
+ });
4793
+ }
4794
+ };
4795
+ }, [stopPreviewEvent, relativeTo]);
4796
+ const set = (key, val) => {
4797
+ const next = { ...value, [key]: val };
4798
+ onChange(next);
4799
+ if (previewingRef.current) {
4800
+ fetchNui(previewEvent, { value: next, relativeTo }).catch(() => {
4801
+ });
4802
+ }
4803
+ };
4804
+ const grab = async () => {
4805
+ try {
4806
+ const resp = await fetchNui(fetchEvent, { relativeTo }, value);
4807
+ if (resp && typeof resp === "object") {
4808
+ const next = {
4809
+ x: Number(resp.x ?? 0),
4810
+ y: Number(resp.y ?? 0),
4811
+ z: Number(resp.z ?? 0),
4812
+ w: Number(resp.w ?? 0)
4813
+ };
4814
+ onChange(next);
4815
+ if (previewingRef.current) {
4816
+ fetchNui(previewEvent, { value: next, relativeTo }).catch(() => {
4817
+ });
4818
+ }
4819
+ }
4820
+ } catch {
4821
+ }
4822
+ };
4823
+ const togglePreview = async () => {
4824
+ const nextState = !previewing;
4825
+ setPreviewing(nextState);
4826
+ previewingRef.current = nextState;
4827
+ if (nextState) {
4828
+ await fetchNui(previewEvent, { value, relativeTo }).catch(() => {
4829
+ });
4830
+ } else {
4831
+ await fetchNui(stopPreviewEvent, { relativeTo }).catch(() => {
4832
+ });
4833
+ }
4834
+ };
4835
+ const reset = () => {
4836
+ onChange({ ...ZERO });
4837
+ if (previewingRef.current) {
4838
+ fetchNui(previewEvent, { value: ZERO, relativeTo }).catch(() => {
4839
+ });
4840
+ }
4841
+ };
4842
+ const numberStyles = {
4843
+ input: { textAlign: "right", fontFamily: "monospace" }
4844
+ };
4845
+ return /* @__PURE__ */ jsxs(
4846
+ Flex,
4847
+ {
4848
+ direction: "column",
4849
+ gap: "xxs",
4850
+ p: "xs",
4851
+ style: {
4852
+ background: alpha(theme2.colors.dark[5], 0.35),
4853
+ border: "0.1vh solid rgba(255,255,255,0.05)",
4854
+ borderRadius: theme2.radius.xs
4855
+ },
4856
+ children: [
4857
+ (label2 || description2) && /* @__PURE__ */ jsxs(Flex, { justify: "space-between", align: "center", gap: "xs", children: [
4858
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 0, style: { minWidth: 0 }, children: [
4859
+ label2 && /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "xxs", children: [
4860
+ /* @__PURE__ */ jsx(MapPin, { size: "1.4vh", color: alpha(color, 0.7) }),
4861
+ /* @__PURE__ */ jsx(
4862
+ Text,
4863
+ {
4864
+ ff: "Akrobat Bold",
4865
+ size: "xxs",
4866
+ tt: "uppercase",
4867
+ lts: "0.05em",
4868
+ c: "rgba(255,255,255,0.75)",
4869
+ children: locale(label2)
4870
+ }
4871
+ ),
4872
+ relativeTo && /* @__PURE__ */ jsxs(Text, { ff: "Akrobat Bold", size: "xxs", c: alpha(color, 0.5), lts: "0.05em", children: [
4873
+ "\xB7 ",
4874
+ locale("RelativeTo"),
4875
+ " ",
4876
+ relativeTo
4877
+ ] })
4878
+ ] }),
4879
+ description2 && /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "dimmed", lh: 1.3, children: locale(description2) })
4880
+ ] }),
4881
+ /* @__PURE__ */ jsxs(Flex, { gap: "xxs", style: { flexShrink: 0 }, children: [
4882
+ /* @__PURE__ */ jsx(PickerButton, { tooltip: locale("GrabMyPosition"), onClick: grab, color, children: /* @__PURE__ */ jsx(Crosshair, { size: "1.4vh", color }) }),
4883
+ /* @__PURE__ */ jsx(
4884
+ PickerButton,
4885
+ {
4886
+ tooltip: previewing ? locale("StopPreview") : locale("PreviewInWorld"),
4887
+ onClick: togglePreview,
4888
+ color,
4889
+ active: previewing,
4890
+ children: previewing ? /* @__PURE__ */ jsx(EyeOff, { size: "1.4vh", color }) : /* @__PURE__ */ jsx(Eye, { size: "1.4vh", color: alpha(color, 0.7) })
4891
+ }
4892
+ ),
4893
+ /* @__PURE__ */ jsx(PickerButton, { tooltip: locale("Reset"), onClick: reset, color: "#ef4444", children: /* @__PURE__ */ jsx(RotateCcw, { size: "1.4vh", color: "#ef4444" }) })
4894
+ ] })
4895
+ ] }),
4896
+ /* @__PURE__ */ jsxs(Flex, { gap: "xxs", children: [
4897
+ /* @__PURE__ */ jsx(
4898
+ NumberInput,
4899
+ {
4900
+ size: "xs",
4901
+ label: "X",
4902
+ value: value.x,
4903
+ onChange: (v) => set("x", Number(v)),
4904
+ decimalScale: 4,
4905
+ step: 0.1,
4906
+ style: { flex: 1 },
4907
+ styles: numberStyles
4908
+ }
4909
+ ),
4910
+ /* @__PURE__ */ jsx(
4911
+ NumberInput,
4912
+ {
4913
+ size: "xs",
4914
+ label: "Y",
4915
+ value: value.y,
4916
+ onChange: (v) => set("y", Number(v)),
4917
+ decimalScale: 4,
4918
+ step: 0.1,
4919
+ style: { flex: 1 },
4920
+ styles: numberStyles
4921
+ }
4922
+ ),
4923
+ /* @__PURE__ */ jsx(
4924
+ NumberInput,
4925
+ {
4926
+ size: "xs",
4927
+ label: "Z",
4928
+ value: value.z,
4929
+ onChange: (v) => set("z", Number(v)),
4930
+ decimalScale: 4,
4931
+ step: 0.1,
4932
+ style: { flex: 1 },
4933
+ styles: numberStyles
4934
+ }
4935
+ ),
4936
+ showHeading && /* @__PURE__ */ jsx(
4937
+ NumberInput,
4938
+ {
4939
+ size: "xs",
4940
+ label: "W",
4941
+ value: value.w,
4942
+ onChange: (v) => set("w", Number(v)),
4943
+ decimalScale: 2,
4944
+ step: 1,
4945
+ min: 0,
4946
+ max: 360,
4947
+ style: { flex: 1 },
4948
+ styles: numberStyles
4949
+ }
4950
+ )
4951
+ ] })
4952
+ ]
4953
+ }
4954
+ );
4955
+ }
4956
+ function PickerButton({
4957
+ children,
4958
+ onClick,
4959
+ tooltip,
4960
+ color,
4961
+ active
4962
+ }) {
4963
+ const theme2 = useMantineTheme();
4964
+ return /* @__PURE__ */ jsx(Tooltip, { label: tooltip, position: "top", withArrow: true, children: /* @__PURE__ */ jsx(
4965
+ motion.button,
4966
+ {
4967
+ onClick,
4968
+ whileHover: { background: alpha(color, 0.18) },
4969
+ whileTap: { scale: 0.95 },
4970
+ style: {
4971
+ background: active ? alpha(color, 0.22) : alpha(color, 0.08),
4972
+ border: `0.1vh solid ${alpha(color, active ? 0.5 : 0.3)}`,
4973
+ borderRadius: theme2.radius.xs,
4974
+ padding: "0.4vh 0.6vh",
4975
+ cursor: "pointer",
4976
+ display: "flex",
4977
+ alignItems: "center",
4978
+ justifyContent: "center"
4979
+ },
4980
+ children
4981
+ }
4982
+ ) });
4983
+ }
4718
4984
  var KeyBindContext = createContext(null);
4719
4985
  function useKeyBindContext() {
4720
4986
  const ctx = useContext(KeyBindContext);
@@ -5177,6 +5443,11 @@ function mergeMantineThemeSafe(base, custom, override) {
5177
5443
  const colors = { ...base.colors };
5178
5444
  if (custom && isValidColorScale(custom)) {
5179
5445
  colors["custom"] = custom;
5446
+ } else if (!colors["custom"]) {
5447
+ const fallback = base.colors && base.colors.dirk;
5448
+ if (fallback && isValidColorScale(fallback)) {
5449
+ colors["custom"] = fallback;
5450
+ }
5180
5451
  }
5181
5452
  return {
5182
5453
  ...base,
@@ -5250,6 +5521,7 @@ function DirkProvider({ children, overideResourceName, themeOverride }) {
5250
5521
  customTheme,
5251
5522
  game
5252
5523
  } = useSettings();
5524
+ localeStore((s) => s.locales);
5253
5525
  useLayoutEffect(() => {
5254
5526
  useSettings.setState({
5255
5527
  overideResourceName
@@ -5270,6 +5542,10 @@ function DirkProvider({ children, overideResourceName, themeOverride }) {
5270
5542
  console.error("Failed to fetch initial settings within dirk-cfx-react:", err);
5271
5543
  });
5272
5544
  }, []);
5545
+ useNuiEvent("UPDATE_DIRK_LIB_SETTINGS", (data) => {
5546
+ if (!data || typeof data !== "object") return;
5547
+ useSettings.setState(data);
5548
+ });
5273
5549
  const mergedTheme = useMemo(
5274
5550
  () => mergeMantineThemeSafe(
5275
5551
  { ...theme_default, primaryColor, primaryShade },
@@ -5293,6 +5569,6 @@ function DirkProvider({ children, overideResourceName, themeOverride }) {
5293
5569
  return /* @__PURE__ */ jsx(MantineProvider, { theme: mergedTheme, defaultColorScheme: "dark", children: /* @__PURE__ */ jsx(DirkErrorBoundary, { children: content }) });
5294
5570
  }
5295
5571
 
5296
- export { AdminPageTitle, AsyncSaveButton, BlipColorSelect, BlipIconSelect, BorderedIcon, ConfigPanel, ConfirmModal, Counter, DirkProvider, FiveMKeyBindInput, FloatingParticles, FormProvider, INPUT_MAPPER_KEYS_BY_PRIMARY, INPUT_MAPPER_PRIMARY_OPTIONS, InfoBox, InputContainer, LevelBanner, LevelPanel, Modal, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PromptModal, SegmentedControl, SegmentedProgress, SelectItem, TestBed, Title, TornEdgeSVGFilter, colorWithAlpha, copyToClipboard, createFormStore, createScriptConfig, createSkill, extractDefaults, fetchLuaTable, fetchNui, gameToMap, getImageShape, getItemImageUrl, getScriptConfigInstance, initialFetches, internalEvent, isEnvBrowser, isProfanity, latPr100, locale, localeStore, mapCenter, mapToGame, noop, numberToRoman, openLink, registerInitialFetch, registerInitialLuaTableFetch, runFetches, splitFAString, updatePresignedURL, uploadImage, useAudio, useAutoFetcher, useForm, useFormActions, useFormError, useFormErrors, useFormField, useFormFields, useItems, useItemsList, useModal, useModalActions, useNavigation, useNavigationStore, useNuiEvent, useProfanityStore, useSettings, useTornEdges };
5572
+ export { AdminPageTitle, AsyncSaveButton, BlipColorSelect, BlipDisplaySelect, BlipIconSelect, BorderedIcon, ConfigPanel, ConfirmModal, Counter, DirkProvider, FiveMKeyBindInput, FloatingParticles, FormProvider, 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, colorWithAlpha, copyToClipboard, createFormStore, createScriptConfig, createSkill, extractDefaults, fetchLuaTable, fetchNui, gameToMap, getImageShape, getItemImageUrl, getScriptConfigInstance, initialFetches, internalEvent, isEnvBrowser, isProfanity, latPr100, locale, localeStore, mapCenter, mapToGame, noop, numberToRoman, openLink, registerInitialFetch, registerInitialLuaTableFetch, runFetches, splitFAString, updatePresignedURL, uploadImage, useAudio, useAutoFetcher, useForm, useFormActions, useFormError, useFormErrors, useFormField, useFormFields, useItems, useItemsList, useModal, useModalActions, useNavigation, useNavigationStore, useNuiEvent, useProfanityStore, useSettings, useTornEdges };
5297
5573
  //# sourceMappingURL=index.js.map
5298
5574
  //# sourceMappingURL=index.js.map