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.
@@ -18,6 +18,11 @@ type BlipColorSelectProps = Omit<SelectProps, "data" | "value" | "onChange" | "s
18
18
  onChange: (id: number) => void;
19
19
  };
20
20
  declare function BlipColorSelect({ value, onChange, label, size, ...rest }: BlipColorSelectProps): react_jsx_runtime.JSX.Element;
21
+ type BlipDisplaySelectProps = Omit<SelectProps, "data" | "value" | "onChange"> & {
22
+ value: number | null;
23
+ onChange: (id: number) => void;
24
+ };
25
+ declare function BlipDisplaySelect({ value, onChange, label, size, ...rest }: BlipDisplaySelectProps): react_jsx_runtime.JSX.Element;
21
26
 
22
27
  type BorderedIconProps = {
23
28
  icon: string;
@@ -820,6 +825,34 @@ type SelectItemProps = {
820
825
  };
821
826
  declare function SelectItem(props: SelectItemProps): react_jsx_runtime.JSX.Element;
822
827
 
828
+ type Vector4Value = {
829
+ x: number;
830
+ y: number;
831
+ z: number;
832
+ w: number;
833
+ };
834
+ type PositionPickerProps = {
835
+ label?: string;
836
+ value: Vector4Value;
837
+ onChange: (v: Vector4Value) => void;
838
+ /**
839
+ * If set, the picker treats `value` as an offset from this entity reference
840
+ * (e.g. "shell"). The Lua side must handle GET_POSITION + relativeTo by
841
+ * returning (playerCoords - entityCoords) instead of world coords, and must
842
+ * resolve the same reference when previewing.
843
+ */
844
+ relativeTo?: string;
845
+ /** Optional NUI event name to fetch the current position. Defaults to GET_POSITION. */
846
+ fetchEvent?: string;
847
+ /** Optional NUI event name to draw a marker at the value. Defaults to PREVIEW_POSITION. */
848
+ previewEvent?: string;
849
+ /** Optional NUI event name to clear the preview marker. Defaults to STOP_PREVIEW_POSITION. */
850
+ stopPreviewEvent?: string;
851
+ description?: string;
852
+ showHeading?: boolean;
853
+ };
854
+ declare function PositionPicker(props: PositionPickerProps): react_jsx_runtime.JSX.Element;
855
+
823
856
  type FiveMControls = {
824
857
  _type: string;
825
858
  _key: string;
@@ -874,4 +907,4 @@ interface TestBedProps {
874
907
  }
875
908
  declare function TestBed({ items, storageKey, disablePersistence, title, }: TestBedProps): react_jsx_runtime.JSX.Element | null;
876
909
 
877
- export { AdminPageTitle, type AdminPageTitleProps, AsyncSaveButton, BlipColorSelect, type BlipColorSelectProps, BlipIconSelect, type BlipIconSelectProps, BorderedIcon, type BorderedIconProps, type ButtonProps, ConfigPanel, type ConfigPanelProps, ConfirmModal, type ConfirmModalProps, Counter, type FiveMControls, FiveMKeyBindInput, FloatingParticles, type FloatingParticlesProps, InfoBox, type InfoBoxProps, InputContainer, type InputContainerProps, LevelBanner, LevelPanel, Modal, ModalContext, type ModalProps, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, type NavItem, NavigationContext, NavigationProvider, type NavigationStore, type ParticleState, type ProgressProps, type Prompt, type PromptButton, PromptModal, type SegmentProps, SegmentedControl, type SegmentedControlProps, SegmentedProgress, SelectItem, type SelectItemProps, type StoreModalProps, TestBed, type TestBedItem, type TestBedProps, Title, type TitleProps, useModal, useModalActions, useNavigation, useNavigationStore };
910
+ export { AdminPageTitle, type AdminPageTitleProps, AsyncSaveButton, BlipColorSelect, type BlipColorSelectProps, BlipDisplaySelect, type BlipDisplaySelectProps, BlipIconSelect, type BlipIconSelectProps, BorderedIcon, type BorderedIconProps, type ButtonProps, ConfigPanel, type ConfigPanelProps, ConfirmModal, type ConfirmModalProps, Counter, type FiveMControls, FiveMKeyBindInput, FloatingParticles, type FloatingParticlesProps, InfoBox, type InfoBoxProps, InputContainer, type InputContainerProps, LevelBanner, LevelPanel, Modal, ModalContext, type ModalProps, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, type NavItem, NavigationContext, NavigationProvider, type NavigationStore, type ParticleState, PositionPicker, type PositionPickerProps, type ProgressProps, type Prompt, type PromptButton, PromptModal, type SegmentProps, SegmentedControl, type SegmentedControlProps, SegmentedProgress, SelectItem, type SelectItemProps, type StoreModalProps, TestBed, type TestBedItem, type TestBedProps, Title, type TitleProps, type Vector4Value, useModal, useModalActions, useNavigation, useNavigationStore };
@@ -18,6 +18,11 @@ type BlipColorSelectProps = Omit<SelectProps, "data" | "value" | "onChange" | "s
18
18
  onChange: (id: number) => void;
19
19
  };
20
20
  declare function BlipColorSelect({ value, onChange, label, size, ...rest }: BlipColorSelectProps): react_jsx_runtime.JSX.Element;
21
+ type BlipDisplaySelectProps = Omit<SelectProps, "data" | "value" | "onChange"> & {
22
+ value: number | null;
23
+ onChange: (id: number) => void;
24
+ };
25
+ declare function BlipDisplaySelect({ value, onChange, label, size, ...rest }: BlipDisplaySelectProps): react_jsx_runtime.JSX.Element;
21
26
 
22
27
  type BorderedIconProps = {
23
28
  icon: string;
@@ -820,6 +825,34 @@ type SelectItemProps = {
820
825
  };
821
826
  declare function SelectItem(props: SelectItemProps): react_jsx_runtime.JSX.Element;
822
827
 
828
+ type Vector4Value = {
829
+ x: number;
830
+ y: number;
831
+ z: number;
832
+ w: number;
833
+ };
834
+ type PositionPickerProps = {
835
+ label?: string;
836
+ value: Vector4Value;
837
+ onChange: (v: Vector4Value) => void;
838
+ /**
839
+ * If set, the picker treats `value` as an offset from this entity reference
840
+ * (e.g. "shell"). The Lua side must handle GET_POSITION + relativeTo by
841
+ * returning (playerCoords - entityCoords) instead of world coords, and must
842
+ * resolve the same reference when previewing.
843
+ */
844
+ relativeTo?: string;
845
+ /** Optional NUI event name to fetch the current position. Defaults to GET_POSITION. */
846
+ fetchEvent?: string;
847
+ /** Optional NUI event name to draw a marker at the value. Defaults to PREVIEW_POSITION. */
848
+ previewEvent?: string;
849
+ /** Optional NUI event name to clear the preview marker. Defaults to STOP_PREVIEW_POSITION. */
850
+ stopPreviewEvent?: string;
851
+ description?: string;
852
+ showHeading?: boolean;
853
+ };
854
+ declare function PositionPicker(props: PositionPickerProps): react_jsx_runtime.JSX.Element;
855
+
823
856
  type FiveMControls = {
824
857
  _type: string;
825
858
  _key: string;
@@ -874,4 +907,4 @@ interface TestBedProps {
874
907
  }
875
908
  declare function TestBed({ items, storageKey, disablePersistence, title, }: TestBedProps): react_jsx_runtime.JSX.Element | null;
876
909
 
877
- export { AdminPageTitle, type AdminPageTitleProps, AsyncSaveButton, BlipColorSelect, type BlipColorSelectProps, BlipIconSelect, type BlipIconSelectProps, BorderedIcon, type BorderedIconProps, type ButtonProps, ConfigPanel, type ConfigPanelProps, ConfirmModal, type ConfirmModalProps, Counter, type FiveMControls, FiveMKeyBindInput, FloatingParticles, type FloatingParticlesProps, InfoBox, type InfoBoxProps, InputContainer, type InputContainerProps, LevelBanner, LevelPanel, Modal, ModalContext, type ModalProps, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, type NavItem, NavigationContext, NavigationProvider, type NavigationStore, type ParticleState, type ProgressProps, type Prompt, type PromptButton, PromptModal, type SegmentProps, SegmentedControl, type SegmentedControlProps, SegmentedProgress, SelectItem, type SelectItemProps, type StoreModalProps, TestBed, type TestBedItem, type TestBedProps, Title, type TitleProps, useModal, useModalActions, useNavigation, useNavigationStore };
910
+ export { AdminPageTitle, type AdminPageTitleProps, AsyncSaveButton, BlipColorSelect, type BlipColorSelectProps, BlipDisplaySelect, type BlipDisplaySelectProps, BlipIconSelect, type BlipIconSelectProps, BorderedIcon, type BorderedIconProps, type ButtonProps, ConfigPanel, type ConfigPanelProps, ConfirmModal, type ConfirmModalProps, Counter, type FiveMControls, FiveMKeyBindInput, FloatingParticles, type FloatingParticlesProps, InfoBox, type InfoBoxProps, InputContainer, type InputContainerProps, LevelBanner, LevelPanel, Modal, ModalContext, type ModalProps, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, type NavItem, NavigationContext, NavigationProvider, type NavigationStore, type ParticleState, PositionPicker, type PositionPickerProps, type ProgressProps, type Prompt, type PromptButton, PromptModal, type SegmentProps, SegmentedControl, type SegmentedControlProps, SegmentedProgress, SelectItem, type SelectItemProps, type StoreModalProps, TestBed, type TestBedItem, type TestBedProps, Title, type TitleProps, type Vector4Value, useModal, useModalActions, useNavigation, useNavigationStore };
@@ -1,12 +1,12 @@
1
- import { Flex, Text, Image, TextInput, Select, Box, useMantineTheme, alpha, Progress, RingProgress, Portal, Button, Loader, ActionIcon, Stack, Group, JsonInput } from '@mantine/core';
1
+ import { Flex, Text, Image, TextInput, Select, Box, useMantineTheme, Tooltip, alpha, Progress, RingProgress, Portal, Button, NumberInput, Loader, ActionIcon, Stack, Group, JsonInput } from '@mantine/core';
2
2
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
  import { createContext, useContext, useRef, useState, useEffect, useMemo } from 'react';
4
4
  import { create, useStore, createStore } from 'zustand';
5
5
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
6
6
  import { motion, AnimatePresence, useMotionValue } from 'framer-motion';
7
+ import { Info, X, AlertTriangle, Trash2, MapPin, Crosshair, EyeOff, Eye, RotateCcw, Check, FlaskConical, ChevronUp, ChevronDown, ArrowLeft, Undo2, Redo2, Save, History, XCircle, Code2, Search, Filter, User } from 'lucide-react';
7
8
  import clickSoundUrl from '../click_sound-PNCRRTM4.mp3';
8
9
  import hoverSoundUrl from '../hover_sound-NBUA222C.mp3';
9
- import { X, AlertTriangle, Trash2, Check, FlaskConical, ChevronUp, ChevronDown, ArrowLeft, Undo2, Redo2, Save, History, XCircle, Code2, RotateCcw, Search, Filter, User } from 'lucide-react';
10
10
  import { QueryClient, QueryClientProvider, useInfiniteQuery } from '@tanstack/react-query';
11
11
 
12
12
  // src/components/BlipSelect.tsx
@@ -1057,6 +1057,31 @@ function BlipColorSelect({ value, onChange, label = "Blip Color", size = "xs", .
1057
1057
  }
1058
1058
  );
1059
1059
  }
1060
+ var BLIP_DISPLAY_DATA = [
1061
+ { value: "2", label: "2 \u2014 Main map + minimap (selectable)" },
1062
+ { value: "3", label: "3 \u2014 Main map only (selectable)" },
1063
+ { value: "4", label: "4 \u2014 Main map only (selectable)" },
1064
+ { value: "5", label: "5 \u2014 Minimap only" },
1065
+ { value: "6", label: "6 \u2014 Main map + minimap (selectable)" },
1066
+ { value: "8", label: "8 \u2014 Main map + minimap (not selectable)" },
1067
+ { value: "9", label: "9 \u2014 Minimap only" },
1068
+ { value: "10", label: "10 \u2014 Main map + minimap (not selectable)" }
1069
+ ];
1070
+ function BlipDisplaySelect({ value, onChange, label = "Blip Display", size = "xs", ...rest }) {
1071
+ return /* @__PURE__ */ jsx(
1072
+ Select,
1073
+ {
1074
+ label,
1075
+ size,
1076
+ ...rest,
1077
+ data: BLIP_DISPLAY_DATA,
1078
+ value: value != null ? String(value) : null,
1079
+ onChange: (val) => val != null && onChange(Number(val)),
1080
+ allowDeselect: false,
1081
+ maxDropdownHeight: 300
1082
+ }
1083
+ );
1084
+ }
1060
1085
 
1061
1086
  // src/utils/colorWithAlpha.ts
1062
1087
  var colorNames = {
@@ -1203,11 +1228,11 @@ var colorNames = {
1203
1228
  Yellow: { r: 255, g: 255, b: 0 },
1204
1229
  YellowGreen: { r: 154, g: 205, b: 50 }
1205
1230
  };
1206
- function colorWithAlpha(color, alpha8) {
1231
+ function colorWithAlpha(color, alpha9) {
1207
1232
  const lowerCasedColor = color.toLowerCase();
1208
1233
  if (colorNames[lowerCasedColor]) {
1209
1234
  const rgb = colorNames[lowerCasedColor];
1210
- return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha8})`;
1235
+ return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha9})`;
1211
1236
  }
1212
1237
  if (/^#([A-Fa-f0-9]{6})$/.test(color)) {
1213
1238
  const hex = color.slice(1);
@@ -1215,12 +1240,12 @@ function colorWithAlpha(color, alpha8) {
1215
1240
  const r = bigint >> 16 & 255;
1216
1241
  const g = bigint >> 8 & 255;
1217
1242
  const b = bigint & 255;
1218
- return `rgba(${r}, ${g}, ${b}, ${alpha8})`;
1243
+ return `rgba(${r}, ${g}, ${b}, ${alpha9})`;
1219
1244
  }
1220
1245
  if (/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/.test(color)) {
1221
1246
  const result = color.match(/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/);
1222
1247
  if (result) {
1223
- return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${alpha8})`;
1248
+ return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${alpha9})`;
1224
1249
  }
1225
1250
  }
1226
1251
  return color;
@@ -1267,13 +1292,24 @@ async function fetchNui(eventName, data, mockData) {
1267
1292
  }
1268
1293
  const overrideResourceName = useSettings.getState().overideResourceName;
1269
1294
  const resourceName = window.GetParentResourceName ? window.GetParentResourceName() : overrideResourceName ? overrideResourceName : "dirk-cfx-react";
1270
- const resp = await fetch(`https://${resourceName}/${eventName}`, options);
1271
- return await resp.json();
1295
+ try {
1296
+ const resp = await fetch(`https://${resourceName}/${eventName}`, options);
1297
+ return await resp.json();
1298
+ } catch {
1299
+ return mockData ?? {};
1300
+ }
1272
1301
  }
1273
1302
  async function registerInitialFetch(eventName, data, mockData) {
1274
1303
  const fetcher = () => fetchNui(eventName, data, mockData);
1275
1304
  return fetcher();
1276
1305
  }
1306
+ var reportedMissing = /* @__PURE__ */ new Set();
1307
+ function reportMissingLocale(key) {
1308
+ if (!key || reportedMissing.has(key)) return;
1309
+ reportedMissing.add(key);
1310
+ fetchNui("REPORT_MISSING_LOCALE", { key }).catch(() => {
1311
+ });
1312
+ }
1277
1313
  var localeStore = create((set, get) => {
1278
1314
  return {
1279
1315
  locales: {
@@ -1281,6 +1317,7 @@ var localeStore = create((set, get) => {
1281
1317
  },
1282
1318
  locale: (key, ...args) => {
1283
1319
  const exists = get().locales[key];
1320
+ if (!exists) reportMissingLocale(key);
1284
1321
  let translation = exists || key;
1285
1322
  if (args.length) {
1286
1323
  translation = translation.replace(/%s/g, () => String(args.shift() || ""));
@@ -1294,6 +1331,14 @@ registerInitialFetch("GET_LOCALES", void 0).then((data) => {
1294
1331
  localeStore.setState({ locales: data });
1295
1332
  }).catch(() => {
1296
1333
  });
1334
+ if (typeof window !== "undefined") {
1335
+ window.addEventListener("message", (event) => {
1336
+ const msg = event.data;
1337
+ if (!msg || msg.action !== "UPDATE_DIRK_LIB_LOCALES") return;
1338
+ if (!msg.data || typeof msg.data !== "object") return;
1339
+ localeStore.setState({ locales: msg.data });
1340
+ });
1341
+ }
1297
1342
  var useItems = create(() => ({}));
1298
1343
  var useItemsList = (excludeItemNames = []) => {
1299
1344
  const excludeSet = new Set(excludeItemNames);
@@ -1933,8 +1978,8 @@ function InputContainer(props) {
1933
1978
  (props.title || props.description) && /* @__PURE__ */ jsxs(
1934
1979
  Flex,
1935
1980
  {
1936
- direction: "column",
1937
- gap: "xxs",
1981
+ align: "center",
1982
+ flex: 1,
1938
1983
  p: props.p == "0" ? "sm" : 0,
1939
1984
  children: [
1940
1985
  props.title && /* @__PURE__ */ jsx(
@@ -1951,12 +1996,26 @@ function InputContainer(props) {
1951
1996
  }
1952
1997
  ),
1953
1998
  props.description && /* @__PURE__ */ jsx(
1954
- Text,
1999
+ Tooltip,
1955
2000
  {
1956
- size: "xs",
1957
- c: "rgba(255, 255, 255, 0.8)",
1958
- fw: 400,
1959
- children: props.description
2001
+ label: props.description,
2002
+ position: "top-end",
2003
+ withArrow: true,
2004
+ multiline: true,
2005
+ maw: "22vh",
2006
+ styles: {
2007
+ tooltip: {
2008
+ background: alpha(theme.colors.dark[7], 0.95),
2009
+ border: `0.1vh solid rgba(255,255,255,0.1)`,
2010
+ color: "rgba(255,255,255,0.75)",
2011
+ fontFamily: "Akrobat Bold",
2012
+ fontSize: "1.3vh",
2013
+ lineHeight: 1.3,
2014
+ padding: "0.6vh 0.8vh",
2015
+ letterSpacing: "0.03em"
2016
+ }
2017
+ },
2018
+ children: /* @__PURE__ */ jsx(Flex, { align: "center", justify: "center", style: { marginLeft: "auto", cursor: "help" }, children: /* @__PURE__ */ jsx(Info, { size: "1.6vh", color: alpha(theme.colors[theme.primaryColor][5], 0.45) }) })
1960
2019
  }
1961
2020
  )
1962
2021
  ]
@@ -1973,13 +2032,7 @@ function InputContainer(props) {
1973
2032
  children: props.error
1974
2033
  }
1975
2034
  ),
1976
- /* @__PURE__ */ jsx(
1977
- Flex,
1978
- {
1979
- ml: "auto",
1980
- children: props.rightSection
1981
- }
1982
- )
2035
+ props.rightSection && /* @__PURE__ */ jsx(Flex, { children: props.rightSection })
1983
2036
  ]
1984
2037
  }
1985
2038
  ),
@@ -3988,6 +4041,219 @@ function SelectItem(props) {
3988
4041
  }
3989
4042
  );
3990
4043
  }
4044
+ var ZERO = { x: 0, y: 0, z: 0, w: 0 };
4045
+ function PositionPicker(props) {
4046
+ const {
4047
+ label,
4048
+ value,
4049
+ onChange,
4050
+ relativeTo,
4051
+ fetchEvent = "GET_POSITION",
4052
+ previewEvent = "PREVIEW_POSITION",
4053
+ stopPreviewEvent = "STOP_PREVIEW_POSITION",
4054
+ description,
4055
+ showHeading = true
4056
+ } = props;
4057
+ const theme = useMantineTheme();
4058
+ const color = theme.colors[theme.primaryColor][5];
4059
+ const [previewing, setPreviewing] = useState(false);
4060
+ const previewingRef = useRef(false);
4061
+ useEffect(() => {
4062
+ return () => {
4063
+ if (previewingRef.current) {
4064
+ fetchNui(stopPreviewEvent, { relativeTo }).catch(() => {
4065
+ });
4066
+ }
4067
+ };
4068
+ }, [stopPreviewEvent, relativeTo]);
4069
+ const set = (key, val) => {
4070
+ const next = { ...value, [key]: val };
4071
+ onChange(next);
4072
+ if (previewingRef.current) {
4073
+ fetchNui(previewEvent, { value: next, relativeTo }).catch(() => {
4074
+ });
4075
+ }
4076
+ };
4077
+ const grab = async () => {
4078
+ try {
4079
+ const resp = await fetchNui(fetchEvent, { relativeTo }, value);
4080
+ if (resp && typeof resp === "object") {
4081
+ const next = {
4082
+ x: Number(resp.x ?? 0),
4083
+ y: Number(resp.y ?? 0),
4084
+ z: Number(resp.z ?? 0),
4085
+ w: Number(resp.w ?? 0)
4086
+ };
4087
+ onChange(next);
4088
+ if (previewingRef.current) {
4089
+ fetchNui(previewEvent, { value: next, relativeTo }).catch(() => {
4090
+ });
4091
+ }
4092
+ }
4093
+ } catch {
4094
+ }
4095
+ };
4096
+ const togglePreview = async () => {
4097
+ const nextState = !previewing;
4098
+ setPreviewing(nextState);
4099
+ previewingRef.current = nextState;
4100
+ if (nextState) {
4101
+ await fetchNui(previewEvent, { value, relativeTo }).catch(() => {
4102
+ });
4103
+ } else {
4104
+ await fetchNui(stopPreviewEvent, { relativeTo }).catch(() => {
4105
+ });
4106
+ }
4107
+ };
4108
+ const reset = () => {
4109
+ onChange({ ...ZERO });
4110
+ if (previewingRef.current) {
4111
+ fetchNui(previewEvent, { value: ZERO, relativeTo }).catch(() => {
4112
+ });
4113
+ }
4114
+ };
4115
+ const numberStyles = {
4116
+ input: { textAlign: "right", fontFamily: "monospace" }
4117
+ };
4118
+ return /* @__PURE__ */ jsxs(
4119
+ Flex,
4120
+ {
4121
+ direction: "column",
4122
+ gap: "xxs",
4123
+ p: "xs",
4124
+ style: {
4125
+ background: alpha(theme.colors.dark[5], 0.35),
4126
+ border: "0.1vh solid rgba(255,255,255,0.05)",
4127
+ borderRadius: theme.radius.xs
4128
+ },
4129
+ children: [
4130
+ (label || description) && /* @__PURE__ */ jsxs(Flex, { justify: "space-between", align: "center", gap: "xs", children: [
4131
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 0, style: { minWidth: 0 }, children: [
4132
+ label && /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "xxs", children: [
4133
+ /* @__PURE__ */ jsx(MapPin, { size: "1.4vh", color: alpha(color, 0.7) }),
4134
+ /* @__PURE__ */ jsx(
4135
+ Text,
4136
+ {
4137
+ ff: "Akrobat Bold",
4138
+ size: "xxs",
4139
+ tt: "uppercase",
4140
+ lts: "0.05em",
4141
+ c: "rgba(255,255,255,0.75)",
4142
+ children: locale(label)
4143
+ }
4144
+ ),
4145
+ relativeTo && /* @__PURE__ */ jsxs(Text, { ff: "Akrobat Bold", size: "xxs", c: alpha(color, 0.5), lts: "0.05em", children: [
4146
+ "\xB7 ",
4147
+ locale("RelativeTo"),
4148
+ " ",
4149
+ relativeTo
4150
+ ] })
4151
+ ] }),
4152
+ description && /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "dimmed", lh: 1.3, children: locale(description) })
4153
+ ] }),
4154
+ /* @__PURE__ */ jsxs(Flex, { gap: "xxs", style: { flexShrink: 0 }, children: [
4155
+ /* @__PURE__ */ jsx(PickerButton, { tooltip: locale("GrabMyPosition"), onClick: grab, color, children: /* @__PURE__ */ jsx(Crosshair, { size: "1.4vh", color }) }),
4156
+ /* @__PURE__ */ jsx(
4157
+ PickerButton,
4158
+ {
4159
+ tooltip: previewing ? locale("StopPreview") : locale("PreviewInWorld"),
4160
+ onClick: togglePreview,
4161
+ color,
4162
+ active: previewing,
4163
+ children: previewing ? /* @__PURE__ */ jsx(EyeOff, { size: "1.4vh", color }) : /* @__PURE__ */ jsx(Eye, { size: "1.4vh", color: alpha(color, 0.7) })
4164
+ }
4165
+ ),
4166
+ /* @__PURE__ */ jsx(PickerButton, { tooltip: locale("Reset"), onClick: reset, color: "#ef4444", children: /* @__PURE__ */ jsx(RotateCcw, { size: "1.4vh", color: "#ef4444" }) })
4167
+ ] })
4168
+ ] }),
4169
+ /* @__PURE__ */ jsxs(Flex, { gap: "xxs", children: [
4170
+ /* @__PURE__ */ jsx(
4171
+ NumberInput,
4172
+ {
4173
+ size: "xs",
4174
+ label: "X",
4175
+ value: value.x,
4176
+ onChange: (v) => set("x", Number(v)),
4177
+ decimalScale: 4,
4178
+ step: 0.1,
4179
+ style: { flex: 1 },
4180
+ styles: numberStyles
4181
+ }
4182
+ ),
4183
+ /* @__PURE__ */ jsx(
4184
+ NumberInput,
4185
+ {
4186
+ size: "xs",
4187
+ label: "Y",
4188
+ value: value.y,
4189
+ onChange: (v) => set("y", Number(v)),
4190
+ decimalScale: 4,
4191
+ step: 0.1,
4192
+ style: { flex: 1 },
4193
+ styles: numberStyles
4194
+ }
4195
+ ),
4196
+ /* @__PURE__ */ jsx(
4197
+ NumberInput,
4198
+ {
4199
+ size: "xs",
4200
+ label: "Z",
4201
+ value: value.z,
4202
+ onChange: (v) => set("z", Number(v)),
4203
+ decimalScale: 4,
4204
+ step: 0.1,
4205
+ style: { flex: 1 },
4206
+ styles: numberStyles
4207
+ }
4208
+ ),
4209
+ showHeading && /* @__PURE__ */ jsx(
4210
+ NumberInput,
4211
+ {
4212
+ size: "xs",
4213
+ label: "W",
4214
+ value: value.w,
4215
+ onChange: (v) => set("w", Number(v)),
4216
+ decimalScale: 2,
4217
+ step: 1,
4218
+ min: 0,
4219
+ max: 360,
4220
+ style: { flex: 1 },
4221
+ styles: numberStyles
4222
+ }
4223
+ )
4224
+ ] })
4225
+ ]
4226
+ }
4227
+ );
4228
+ }
4229
+ function PickerButton({
4230
+ children,
4231
+ onClick,
4232
+ tooltip,
4233
+ color,
4234
+ active
4235
+ }) {
4236
+ const theme = useMantineTheme();
4237
+ return /* @__PURE__ */ jsx(Tooltip, { label: tooltip, position: "top", withArrow: true, children: /* @__PURE__ */ jsx(
4238
+ motion.button,
4239
+ {
4240
+ onClick,
4241
+ whileHover: { background: alpha(color, 0.18) },
4242
+ whileTap: { scale: 0.95 },
4243
+ style: {
4244
+ background: active ? alpha(color, 0.22) : alpha(color, 0.08),
4245
+ border: `0.1vh solid ${alpha(color, active ? 0.5 : 0.3)}`,
4246
+ borderRadius: theme.radius.xs,
4247
+ padding: "0.4vh 0.6vh",
4248
+ cursor: "pointer",
4249
+ display: "flex",
4250
+ alignItems: "center",
4251
+ justifyContent: "center"
4252
+ },
4253
+ children
4254
+ }
4255
+ ) });
4256
+ }
3991
4257
  var KeyBindContext = createContext(null);
3992
4258
  function useKeyBindContext() {
3993
4259
  const ctx = useContext(KeyBindContext);
@@ -4271,6 +4537,6 @@ function TestBed({
4271
4537
  );
4272
4538
  }
4273
4539
 
4274
- export { AdminPageTitle, AsyncSaveButton, BlipColorSelect, BlipIconSelect, BorderedIcon, ConfigPanel, ConfirmModal, Counter, FiveMKeyBindInput, FloatingParticles, InfoBox, InputContainer, LevelBanner, LevelPanel, Modal, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PromptModal, SegmentedControl, SegmentedProgress, SelectItem, TestBed, Title, useModal, useModalActions, useNavigation, useNavigationStore };
4540
+ export { AdminPageTitle, AsyncSaveButton, BlipColorSelect, BlipDisplaySelect, BlipIconSelect, BorderedIcon, ConfigPanel, ConfirmModal, Counter, FiveMKeyBindInput, FloatingParticles, InfoBox, InputContainer, LevelBanner, LevelPanel, Modal, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PositionPicker, PromptModal, SegmentedControl, SegmentedProgress, SelectItem, TestBed, Title, useModal, useModalActions, useNavigation, useNavigationStore };
4275
4541
  //# sourceMappingURL=index.js.map
4276
4542
  //# sourceMappingURL=index.js.map