dirk-cfx-react 1.1.64 → 1.1.66

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.
@@ -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;
@@ -1335,6 +1360,20 @@ registerInitialFetch("FETCH_ALL_ITEMS", null, {
1335
1360
  useItems.setState(fetchedItems);
1336
1361
  }).catch(() => {
1337
1362
  });
1363
+ var useFrameworkGroups = zustand.create(() => ({
1364
+ jobs: [],
1365
+ gangs: [],
1366
+ loaded: false
1367
+ }));
1368
+ registerInitialFetch("GET_FRAMEWORK_GROUPS", void 0).then((data) => {
1369
+ useFrameworkGroups.setState({
1370
+ jobs: Array.isArray(data?.jobs) ? data.jobs : [],
1371
+ gangs: Array.isArray(data?.gangs) ? data.gangs : [],
1372
+ loaded: true
1373
+ });
1374
+ }).catch(() => {
1375
+ useFrameworkGroups.setState({ loaded: true });
1376
+ });
1338
1377
 
1339
1378
  // src/utils/inputMapper.ts
1340
1379
  var INPUT_MAPPER_PRIMARY_OPTIONS = [
@@ -4023,6 +4062,307 @@ function SelectItem(props) {
4023
4062
  }
4024
4063
  );
4025
4064
  }
4065
+ var ZERO = { x: 0, y: 0, z: 0, w: 0 };
4066
+ function PositionPicker(props) {
4067
+ const {
4068
+ label,
4069
+ value,
4070
+ onChange,
4071
+ relativeTo,
4072
+ fetchEvent = "GET_POSITION",
4073
+ previewEvent = "PREVIEW_POSITION",
4074
+ stopPreviewEvent = "STOP_PREVIEW_POSITION",
4075
+ description,
4076
+ showHeading = true
4077
+ } = props;
4078
+ const theme = core.useMantineTheme();
4079
+ const color = theme.colors[theme.primaryColor][5];
4080
+ const [previewing, setPreviewing] = react.useState(false);
4081
+ const previewingRef = react.useRef(false);
4082
+ react.useEffect(() => {
4083
+ return () => {
4084
+ if (previewingRef.current) {
4085
+ fetchNui(stopPreviewEvent, { relativeTo }).catch(() => {
4086
+ });
4087
+ }
4088
+ };
4089
+ }, [stopPreviewEvent, relativeTo]);
4090
+ const set = (key, val) => {
4091
+ const next = { ...value, [key]: val };
4092
+ onChange(next);
4093
+ if (previewingRef.current) {
4094
+ fetchNui(previewEvent, { value: next, relativeTo }).catch(() => {
4095
+ });
4096
+ }
4097
+ };
4098
+ const grab = async () => {
4099
+ try {
4100
+ const resp = await fetchNui(fetchEvent, { relativeTo }, value);
4101
+ if (resp && typeof resp === "object") {
4102
+ const next = {
4103
+ x: Number(resp.x ?? 0),
4104
+ y: Number(resp.y ?? 0),
4105
+ z: Number(resp.z ?? 0),
4106
+ w: Number(resp.w ?? 0)
4107
+ };
4108
+ onChange(next);
4109
+ if (previewingRef.current) {
4110
+ fetchNui(previewEvent, { value: next, relativeTo }).catch(() => {
4111
+ });
4112
+ }
4113
+ }
4114
+ } catch {
4115
+ }
4116
+ };
4117
+ const togglePreview = async () => {
4118
+ const nextState = !previewing;
4119
+ setPreviewing(nextState);
4120
+ previewingRef.current = nextState;
4121
+ if (nextState) {
4122
+ await fetchNui(previewEvent, { value, relativeTo }).catch(() => {
4123
+ });
4124
+ } else {
4125
+ await fetchNui(stopPreviewEvent, { relativeTo }).catch(() => {
4126
+ });
4127
+ }
4128
+ };
4129
+ const reset = () => {
4130
+ onChange({ ...ZERO });
4131
+ if (previewingRef.current) {
4132
+ fetchNui(previewEvent, { value: ZERO, relativeTo }).catch(() => {
4133
+ });
4134
+ }
4135
+ };
4136
+ const numberStyles = {
4137
+ input: { textAlign: "right", fontFamily: "monospace" }
4138
+ };
4139
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4140
+ core.Flex,
4141
+ {
4142
+ direction: "column",
4143
+ gap: "xxs",
4144
+ p: "xs",
4145
+ style: {
4146
+ background: core.alpha(theme.colors.dark[5], 0.35),
4147
+ border: "0.1vh solid rgba(255,255,255,0.05)",
4148
+ borderRadius: theme.radius.xs
4149
+ },
4150
+ children: [
4151
+ (label || description) && /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { justify: "space-between", align: "center", gap: "xs", children: [
4152
+ /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", gap: 0, style: { minWidth: 0 }, children: [
4153
+ label && /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "xxs", children: [
4154
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MapPin, { size: "1.4vh", color: core.alpha(color, 0.7) }),
4155
+ /* @__PURE__ */ jsxRuntime.jsx(
4156
+ core.Text,
4157
+ {
4158
+ ff: "Akrobat Bold",
4159
+ size: "xxs",
4160
+ tt: "uppercase",
4161
+ lts: "0.05em",
4162
+ c: "rgba(255,255,255,0.75)",
4163
+ children: locale(label)
4164
+ }
4165
+ ),
4166
+ relativeTo && /* @__PURE__ */ jsxRuntime.jsxs(core.Text, { ff: "Akrobat Bold", size: "xxs", c: core.alpha(color, 0.5), lts: "0.05em", children: [
4167
+ "\xB7 ",
4168
+ locale("RelativeTo"),
4169
+ " ",
4170
+ relativeTo
4171
+ ] })
4172
+ ] }),
4173
+ description && /* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", c: "dimmed", lh: 1.3, children: locale(description) })
4174
+ ] }),
4175
+ /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { gap: "xxs", style: { flexShrink: 0 }, children: [
4176
+ /* @__PURE__ */ jsxRuntime.jsx(PickerButton, { tooltip: locale("GrabMyPosition"), onClick: grab, color, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crosshair, { size: "1.4vh", color }) }),
4177
+ /* @__PURE__ */ jsxRuntime.jsx(
4178
+ PickerButton,
4179
+ {
4180
+ tooltip: previewing ? locale("StopPreview") : locale("PreviewInWorld"),
4181
+ onClick: togglePreview,
4182
+ color,
4183
+ active: previewing,
4184
+ 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) })
4185
+ }
4186
+ ),
4187
+ /* @__PURE__ */ jsxRuntime.jsx(PickerButton, { tooltip: locale("Reset"), onClick: reset, color: "#ef4444", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { size: "1.4vh", color: "#ef4444" }) })
4188
+ ] })
4189
+ ] }),
4190
+ /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { gap: "xxs", children: [
4191
+ /* @__PURE__ */ jsxRuntime.jsx(
4192
+ core.NumberInput,
4193
+ {
4194
+ size: "xs",
4195
+ label: "X",
4196
+ value: value.x,
4197
+ onChange: (v) => set("x", Number(v)),
4198
+ decimalScale: 4,
4199
+ step: 0.1,
4200
+ style: { flex: 1 },
4201
+ styles: numberStyles
4202
+ }
4203
+ ),
4204
+ /* @__PURE__ */ jsxRuntime.jsx(
4205
+ core.NumberInput,
4206
+ {
4207
+ size: "xs",
4208
+ label: "Y",
4209
+ value: value.y,
4210
+ onChange: (v) => set("y", Number(v)),
4211
+ decimalScale: 4,
4212
+ step: 0.1,
4213
+ style: { flex: 1 },
4214
+ styles: numberStyles
4215
+ }
4216
+ ),
4217
+ /* @__PURE__ */ jsxRuntime.jsx(
4218
+ core.NumberInput,
4219
+ {
4220
+ size: "xs",
4221
+ label: "Z",
4222
+ value: value.z,
4223
+ onChange: (v) => set("z", Number(v)),
4224
+ decimalScale: 4,
4225
+ step: 0.1,
4226
+ style: { flex: 1 },
4227
+ styles: numberStyles
4228
+ }
4229
+ ),
4230
+ showHeading && /* @__PURE__ */ jsxRuntime.jsx(
4231
+ core.NumberInput,
4232
+ {
4233
+ size: "xs",
4234
+ label: "W",
4235
+ value: value.w,
4236
+ onChange: (v) => set("w", Number(v)),
4237
+ decimalScale: 2,
4238
+ step: 1,
4239
+ min: 0,
4240
+ max: 360,
4241
+ style: { flex: 1 },
4242
+ styles: numberStyles
4243
+ }
4244
+ )
4245
+ ] })
4246
+ ]
4247
+ }
4248
+ );
4249
+ }
4250
+ function PickerButton({
4251
+ children,
4252
+ onClick,
4253
+ tooltip,
4254
+ color,
4255
+ active
4256
+ }) {
4257
+ const theme = core.useMantineTheme();
4258
+ return /* @__PURE__ */ jsxRuntime.jsx(core.Tooltip, { label: tooltip, position: "top", withArrow: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4259
+ framerMotion.motion.button,
4260
+ {
4261
+ onClick,
4262
+ whileHover: { background: core.alpha(color, 0.18) },
4263
+ whileTap: { scale: 0.95 },
4264
+ style: {
4265
+ background: active ? core.alpha(color, 0.22) : core.alpha(color, 0.08),
4266
+ border: `0.1vh solid ${core.alpha(color, active ? 0.5 : 0.3)}`,
4267
+ borderRadius: theme.radius.xs,
4268
+ padding: "0.4vh 0.6vh",
4269
+ cursor: "pointer",
4270
+ display: "flex",
4271
+ alignItems: "center",
4272
+ justifyContent: "center"
4273
+ },
4274
+ children
4275
+ }
4276
+ ) });
4277
+ }
4278
+ var GroupSelectContext = react.createContext(null);
4279
+ function GroupSelect({
4280
+ value,
4281
+ onChange,
4282
+ type,
4283
+ children,
4284
+ style
4285
+ }) {
4286
+ return /* @__PURE__ */ jsxRuntime.jsx(GroupSelectContext.Provider, { value: { value, onChange, type }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "0.4vh", ...style }, children }) });
4287
+ }
4288
+ function filterByType(jobs, gangs, type) {
4289
+ if (type === "job") return jobs;
4290
+ if (type === "gang") return gangs;
4291
+ return [...jobs, ...gangs];
4292
+ }
4293
+ function GroupName(props) {
4294
+ const ctx = react.useContext(GroupSelectContext);
4295
+ const jobs = useFrameworkGroups((s) => s.jobs);
4296
+ const gangs = useFrameworkGroups((s) => s.gangs);
4297
+ const inCompound = ctx !== null;
4298
+ const currentValue = inCompound ? ctx.value.name : props.value;
4299
+ const filterType = inCompound ? ctx.type : props.type;
4300
+ const list = filterByType(jobs, gangs, filterType);
4301
+ const data = filterType === void 0 ? [
4302
+ { group: locale("Jobs") || "Jobs", items: jobs.map((g) => ({ value: g.name, label: g.label })) },
4303
+ { group: locale("Gangs") || "Gangs", items: gangs.map((g) => ({ value: g.name, label: g.label })) }
4304
+ ] : list.map((g) => ({ value: g.name, label: g.label }));
4305
+ return /* @__PURE__ */ jsxRuntime.jsx(
4306
+ core.Select,
4307
+ {
4308
+ label: props.label,
4309
+ description: props.description,
4310
+ placeholder: props.placeholder ?? (locale("SelectGroup") || "Select\u2026"),
4311
+ size: props.size ?? "xs",
4312
+ disabled: props.disabled,
4313
+ style: props.style,
4314
+ data,
4315
+ value: currentValue ?? null,
4316
+ searchable: true,
4317
+ onChange: (v) => {
4318
+ const name = v ?? "";
4319
+ if (inCompound) {
4320
+ ctx.onChange({ name: name || void 0, grade: void 0 });
4321
+ } else if (props.onChange) {
4322
+ props.onChange(name);
4323
+ }
4324
+ },
4325
+ allowDeselect: false
4326
+ }
4327
+ );
4328
+ }
4329
+ function GroupRank(props) {
4330
+ const ctx = react.useContext(GroupSelectContext);
4331
+ if (ctx === null) {
4332
+ throw new Error("<GroupRank> must be a child of <GroupSelect>");
4333
+ }
4334
+ const jobs = useFrameworkGroups((s) => s.jobs);
4335
+ const gangs = useFrameworkGroups((s) => s.gangs);
4336
+ const all = [...jobs, ...gangs];
4337
+ const selectedGroup = all.find((g) => g.name === ctx.value.name) ?? null;
4338
+ const grades = selectedGroup?.grades ?? [];
4339
+ const data = grades.map((g) => ({
4340
+ value: String(g.grade),
4341
+ label: `${g.grade} \u2014 ${g.label || g.name}${g.isBoss ? " (boss)" : ""}`
4342
+ }));
4343
+ return /* @__PURE__ */ jsxRuntime.jsx(
4344
+ core.Select,
4345
+ {
4346
+ label: props.label,
4347
+ description: props.description,
4348
+ placeholder: props.placeholder ?? (locale("SelectGrade") || "Select grade\u2026"),
4349
+ size: props.size ?? "xs",
4350
+ style: props.style,
4351
+ data,
4352
+ value: ctx.value.grade != null ? String(ctx.value.grade) : null,
4353
+ onChange: (v) => {
4354
+ ctx.onChange({
4355
+ ...ctx.value,
4356
+ grade: v != null ? Number(v) : void 0
4357
+ });
4358
+ },
4359
+ disabled: !selectedGroup || grades.length === 0,
4360
+ allowDeselect: false
4361
+ }
4362
+ );
4363
+ }
4364
+ GroupSelect.Name = GroupName;
4365
+ GroupSelect.Rank = GroupRank;
4026
4366
  var KeyBindContext = react.createContext(null);
4027
4367
  function useKeyBindContext() {
4028
4368
  const ctx = react.useContext(KeyBindContext);
@@ -4309,6 +4649,7 @@ function TestBed({
4309
4649
  exports.AdminPageTitle = AdminPageTitle;
4310
4650
  exports.AsyncSaveButton = AsyncSaveButton;
4311
4651
  exports.BlipColorSelect = BlipColorSelect;
4652
+ exports.BlipDisplaySelect = BlipDisplaySelect;
4312
4653
  exports.BlipIconSelect = BlipIconSelect;
4313
4654
  exports.BorderedIcon = BorderedIcon;
4314
4655
  exports.ConfigPanel = ConfigPanel;
@@ -4316,6 +4657,9 @@ exports.ConfirmModal = ConfirmModal;
4316
4657
  exports.Counter = Counter;
4317
4658
  exports.FiveMKeyBindInput = FiveMKeyBindInput;
4318
4659
  exports.FloatingParticles = FloatingParticles;
4660
+ exports.GroupName = GroupName;
4661
+ exports.GroupRank = GroupRank;
4662
+ exports.GroupSelect = GroupSelect;
4319
4663
  exports.InfoBox = InfoBox;
4320
4664
  exports.InputContainer = InputContainer;
4321
4665
  exports.LevelBanner = LevelBanner;
@@ -4330,6 +4674,7 @@ exports.MotionText = MotionText;
4330
4674
  exports.NavBar = NavBar;
4331
4675
  exports.NavigationContext = NavigationContext;
4332
4676
  exports.NavigationProvider = NavigationProvider;
4677
+ exports.PositionPicker = PositionPicker;
4333
4678
  exports.PromptModal = PromptModal;
4334
4679
  exports.SegmentedControl = SegmentedControl;
4335
4680
  exports.SegmentedProgress = SegmentedProgress;