dirk-cfx-react 1.1.56 → 1.1.62

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.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  var core = require('@mantine/core');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
- var React4 = require('react');
5
+ var React5 = require('react');
6
6
  var zustand = require('zustand');
7
7
  var axios = require('axios');
8
8
  var reactFontawesome = require('@fortawesome/react-fontawesome');
@@ -24,7 +24,7 @@ var freeSolidSvgIcons = require('@fortawesome/free-solid-svg-icons');
24
24
 
25
25
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
26
26
 
27
- var React4__default = /*#__PURE__*/_interopDefault(React4);
27
+ var React5__default = /*#__PURE__*/_interopDefault(React5);
28
28
  var axios__default = /*#__PURE__*/_interopDefault(axios);
29
29
  var clickSoundUrl__default = /*#__PURE__*/_interopDefault(clickSoundUrl);
30
30
  var hoverSoundUrl__default = /*#__PURE__*/_interopDefault(hoverSoundUrl);
@@ -1333,12 +1333,10 @@ async function runFetches() {
1333
1333
  );
1334
1334
  }
1335
1335
  var useAutoFetcher = () => {
1336
- React4.useEffect(() => {
1336
+ React5.useEffect(() => {
1337
1337
  if (isEnvBrowser()) return;
1338
- const run = async () => {
1339
- await runFetches();
1340
- };
1341
- run();
1338
+ runFetches().catch(() => {
1339
+ });
1342
1340
  }, []);
1343
1341
  };
1344
1342
  var fetchLuaTable = (tableName, mockData) => {
@@ -1383,6 +1381,7 @@ var localeStore = zustand.create((set, get) => {
1383
1381
  var locale = localeStore.getState().locale;
1384
1382
  registerInitialFetch("GET_LOCALES", void 0).then((data) => {
1385
1383
  localeStore.setState({ locales: data });
1384
+ }).catch(() => {
1386
1385
  });
1387
1386
 
1388
1387
  // src/utils/map.ts
@@ -1814,7 +1813,7 @@ function createSkill(defaultSettings) {
1814
1813
  }));
1815
1814
  const useSkill = (xp) => {
1816
1815
  const { settings, levelMap } = useStore4();
1817
- return React4.useMemo(() => {
1816
+ return React5.useMemo(() => {
1818
1817
  const currentLevel = getLevelFromXP(xp, levelMap, settings);
1819
1818
  const nextLevel = Math.min(currentLevel + 1, settings.maxLevel);
1820
1819
  const currentLevelXP = levelMap[currentLevel.toString()] || 0;
@@ -1900,6 +1899,7 @@ registerInitialFetch("FETCH_ALL_ITEMS", null, {
1900
1899
  }).then((fetchedItems) => {
1901
1900
  if (!fetchedItems) return;
1902
1901
  useItems.setState(fetchedItems);
1902
+ }).catch(() => {
1903
1903
  });
1904
1904
 
1905
1905
  // src/utils/inputMapper.ts
@@ -2270,8 +2270,8 @@ var FloatingParticles = ({
2270
2270
  mouseRepelStrength = 50,
2271
2271
  backgroundColor = "transparent"
2272
2272
  }) => {
2273
- const containerRef = React4.useRef(null);
2274
- const [particles, setParticles] = React4.useState([]);
2273
+ const containerRef = React5.useRef(null);
2274
+ const [particles, setParticles] = React5.useState([]);
2275
2275
  const mouseX = framerMotion.useMotionValue(0);
2276
2276
  const mouseY = framerMotion.useMotionValue(0);
2277
2277
  const durationMap = {
@@ -2284,7 +2284,7 @@ var FloatingParticles = ({
2284
2284
  const x = Math.sin(seed) * 1e4;
2285
2285
  return x - Math.floor(x);
2286
2286
  };
2287
- React4.useEffect(() => {
2287
+ React5.useEffect(() => {
2288
2288
  if (!containerRef.current) return;
2289
2289
  const bounds = containerRef.current.getBoundingClientRect();
2290
2290
  const newParticles = [...Array(particleCount)].map((_, i) => {
@@ -2305,7 +2305,7 @@ var FloatingParticles = ({
2305
2305
  });
2306
2306
  setParticles(newParticles);
2307
2307
  }, [particleCount, icons.length, duration.base, duration.variance]);
2308
- React4.useEffect(() => {
2308
+ React5.useEffect(() => {
2309
2309
  if (!containerRef.current) return;
2310
2310
  const handleMouseMove = (e) => {
2311
2311
  const bounds = containerRef.current.getBoundingClientRect();
@@ -2354,7 +2354,7 @@ var FloatingParticles = ({
2354
2354
  container.removeEventListener("mouseleave", handleMouseLeave);
2355
2355
  };
2356
2356
  }, [mouseX, mouseY, mouseRepelDistance, mouseRepelStrength]);
2357
- React4.useEffect(() => {
2357
+ React5.useEffect(() => {
2358
2358
  const handleResize = () => {
2359
2359
  if (!containerRef.current) return;
2360
2360
  const bounds = containerRef.current.getBoundingClientRect();
@@ -2782,23 +2782,23 @@ function Segment(props) {
2782
2782
  }
2783
2783
  );
2784
2784
  }
2785
- var NavigationContext = React4.createContext(null);
2785
+ var NavigationContext = React5.createContext(null);
2786
2786
  function useNavigation(selector) {
2787
- const navigation = React4.useContext(NavigationContext);
2787
+ const navigation = React5.useContext(NavigationContext);
2788
2788
  if (!navigation) {
2789
2789
  throw new Error("useNavigation must be used within a NavigationProvider");
2790
2790
  }
2791
2791
  return zustand.useStore(navigation, selector);
2792
2792
  }
2793
2793
  function useNavigationStore() {
2794
- const navigation = React4.useContext(NavigationContext);
2794
+ const navigation = React5.useContext(NavigationContext);
2795
2795
  if (!navigation) {
2796
2796
  throw new Error("useNavigationStore must be used within a NavigationProvider");
2797
2797
  }
2798
2798
  return navigation;
2799
2799
  }
2800
2800
  function NavigationProvider({ children, defaultPage }) {
2801
- const storeRef = React4.useRef(
2801
+ const storeRef = React5.useRef(
2802
2802
  zustand.create(() => ({
2803
2803
  pageId: defaultPage || "home"
2804
2804
  }))
@@ -3155,6 +3155,7 @@ function Modal({
3155
3155
  children
3156
3156
  }) {
3157
3157
  const theme2 = core.useMantineTheme();
3158
+ const pointerDownOnOverlay = React5.useRef(false);
3158
3159
  return /* @__PURE__ */ jsxRuntime.jsx(core.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
3159
3160
  framerMotion.motion.div,
3160
3161
  {
@@ -3170,7 +3171,14 @@ function Modal({
3170
3171
  justifyContent: "center",
3171
3172
  background: "rgba(0,0,0,0.65)"
3172
3173
  },
3173
- onClick: clickOutside ? onClose : void 0,
3174
+ onPointerDown: (e) => {
3175
+ pointerDownOnOverlay.current = e.target === e.currentTarget;
3176
+ },
3177
+ onClick: (e) => {
3178
+ if (clickOutside && e.target === e.currentTarget && pointerDownOnOverlay.current) {
3179
+ onClose();
3180
+ }
3181
+ },
3174
3182
  children: /* @__PURE__ */ jsxRuntime.jsxs(
3175
3183
  framerMotion.motion.div,
3176
3184
  {
@@ -3178,7 +3186,6 @@ function Modal({
3178
3186
  animate: { opacity: 1, scale: 1, y: 0 },
3179
3187
  exit: { opacity: 0, scale: 0.96, y: 8 },
3180
3188
  transition: { duration: 0.18, ease: "easeOut" },
3181
- onClick: (e) => e.stopPropagation(),
3182
3189
  style: {
3183
3190
  background: core.alpha(theme2.colors.dark[9], 0.98),
3184
3191
  border: `0.1vh solid ${theme2.colors.dark[7]}`,
@@ -3275,7 +3282,7 @@ function Modal({
3275
3282
  children: description2
3276
3283
  }
3277
3284
  ) }),
3278
- children
3285
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, minHeight: 0, display: "flex", flexDirection: "column" }, children })
3279
3286
  ]
3280
3287
  }
3281
3288
  )
@@ -3329,9 +3336,9 @@ function PromptModal(props) {
3329
3336
  }
3330
3337
  );
3331
3338
  }
3332
- var ModalContext = React4.createContext(null);
3339
+ var ModalContext = React5.createContext(null);
3333
3340
  function useModal(selector) {
3334
- const modal = React4.useContext(ModalContext);
3341
+ const modal = React5.useContext(ModalContext);
3335
3342
  if (!modal) {
3336
3343
  throw new Error("useModal must be used within a ModalProvider");
3337
3344
  }
@@ -3359,7 +3366,7 @@ function StoreModal() {
3359
3366
  ) });
3360
3367
  }
3361
3368
  function ModalProvider({ children }) {
3362
- const storeRef = React4.useRef(
3369
+ const storeRef = React5.useRef(
3363
3370
  zustand.create(() => ({
3364
3371
  active: null
3365
3372
  }))
@@ -3370,7 +3377,7 @@ function ModalProvider({ children }) {
3370
3377
  ] });
3371
3378
  }
3372
3379
  function useModalActions() {
3373
- const modal = React4.useContext(ModalContext);
3380
+ const modal = React5.useContext(ModalContext);
3374
3381
  if (!modal) throw new Error("useModalActions must be used within a ModalProvider");
3375
3382
  const showModal = (openModal) => {
3376
3383
  modal.setState({ active: openModal });
@@ -3390,7 +3397,7 @@ function ConfirmModal({
3390
3397
  zIndex = 200
3391
3398
  }) {
3392
3399
  const theme2 = core.useMantineTheme();
3393
- const [typed, setTyped] = React4.useState("");
3400
+ const [typed, setTyped] = React5.useState("");
3394
3401
  const canConfirm = !confirmText || typed === confirmText;
3395
3402
  return /* @__PURE__ */ jsxRuntime.jsx(core.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
3396
3403
  framerMotion.motion.div,
@@ -3868,38 +3875,38 @@ function createFormStore(initialValues, validationRules, onSubmit) {
3868
3875
  }
3869
3876
  }));
3870
3877
  }
3871
- var FormContext = React4.createContext(null);
3878
+ var FormContext = React5.createContext(null);
3872
3879
  function FormProvider({
3873
3880
  initialValues,
3874
3881
  validate,
3875
3882
  onSubmit,
3876
3883
  children
3877
3884
  }) {
3878
- const storeRef = React4.useRef(
3885
+ const storeRef = React5.useRef(
3879
3886
  createFormStore(initialValues, validate, onSubmit)
3880
3887
  );
3881
3888
  return /* @__PURE__ */ jsxRuntime.jsx(FormContext.Provider, { value: storeRef.current, children });
3882
3889
  }
3883
3890
  function useForm() {
3884
- const store = React4.useContext(FormContext);
3891
+ const store = React5.useContext(FormContext);
3885
3892
  if (!store) {
3886
3893
  throw new Error("useForm must be used inside <FormProvider>");
3887
3894
  }
3888
3895
  const state = zustand.useStore(store);
3889
- const changedFields = React4.useMemo(() => {
3896
+ const changedFields = React5.useMemo(() => {
3890
3897
  return collectChangedPaths(state.values, state.initialValues);
3891
3898
  }, [state.values, state.initialValues]);
3892
3899
  return { ...state, changedFields, changedCount: changedFields.length };
3893
3900
  }
3894
3901
  function useFormField(path) {
3895
- const store = React4.useContext(FormContext);
3902
+ const store = React5.useContext(FormContext);
3896
3903
  if (!store) {
3897
3904
  throw new Error("useFormField must be used inside <FormProvider>");
3898
3905
  }
3899
3906
  return zustand.useStore(store, (s) => getNested(s.values, path));
3900
3907
  }
3901
3908
  function useFormFields(...paths) {
3902
- const store = React4.useContext(FormContext);
3909
+ const store = React5.useContext(FormContext);
3903
3910
  if (!store) {
3904
3911
  throw new Error("useFormFields must be used inside <FormProvider>");
3905
3912
  }
@@ -3912,14 +3919,14 @@ function useFormFields(...paths) {
3912
3919
  });
3913
3920
  }
3914
3921
  function useFormError(path) {
3915
- const store = React4.useContext(FormContext);
3922
+ const store = React5.useContext(FormContext);
3916
3923
  if (!store) {
3917
3924
  throw new Error("useFormError must be used inside <FormProvider>");
3918
3925
  }
3919
3926
  return zustand.useStore(store, (s) => s.errors[path]);
3920
3927
  }
3921
3928
  function useFormErrors(...paths) {
3922
- const store = React4.useContext(FormContext);
3929
+ const store = React5.useContext(FormContext);
3923
3930
  if (!store) {
3924
3931
  throw new Error("useFormErrors must be used inside <FormProvider>");
3925
3932
  }
@@ -3932,18 +3939,18 @@ function useFormErrors(...paths) {
3932
3939
  });
3933
3940
  }
3934
3941
  function useFormActions() {
3935
- const store = React4.useContext(FormContext);
3942
+ const store = React5.useContext(FormContext);
3936
3943
  if (!store) {
3937
3944
  throw new Error("useFormActions must be used inside <FormProvider>");
3938
3945
  }
3939
3946
  return store.getState();
3940
3947
  }
3941
3948
  var useNuiEvent = (action, handler) => {
3942
- const savedHandler = React4.useRef(noop);
3943
- React4.useEffect(() => {
3949
+ const savedHandler = React5.useRef(noop);
3950
+ React5.useEffect(() => {
3944
3951
  savedHandler.current = handler;
3945
3952
  }, [handler]);
3946
- React4.useEffect(() => {
3953
+ React5.useEffect(() => {
3947
3954
  const eventListener = (event) => {
3948
3955
  const { action: eventAction, data } = event.data;
3949
3956
  if (savedHandler.current) {
@@ -3957,42 +3964,42 @@ var useNuiEvent = (action, handler) => {
3957
3964
  }, [action]);
3958
3965
  };
3959
3966
  var _instance = null;
3960
- function getScriptSettingsInstance() {
3961
- if (!_instance) throw new Error("[dirk-cfx-react] createScriptSettings must be called before using SettingsPanel");
3967
+ function getScriptConfigInstance() {
3968
+ if (!_instance) throw new Error("[dirk-cfx-react] createScriptConfig must be called before using ConfigPanel");
3962
3969
  return _instance;
3963
3970
  }
3964
- function createScriptSettings(defaultValue) {
3971
+ function createScriptConfig(defaultValue) {
3965
3972
  const store = zustand.create(() => defaultValue);
3966
3973
  let clientVersion = 0;
3967
- const useScriptSettingHooks = () => {
3968
- useNuiEvent("UPDATE_SCRIPT_SETTINGS", (data) => {
3974
+ const useScriptConfigHooks = () => {
3975
+ useNuiEvent("UPDATE_SCRIPT_CONFIG", (data) => {
3969
3976
  if (!data) return;
3970
3977
  if (typeof data.clientVersion === "number") {
3971
3978
  clientVersion = data.clientVersion;
3972
3979
  }
3973
- if (data.settings && typeof data.settings === "object") {
3974
- store.setState((prev) => ({ ...prev, ...data.settings }));
3980
+ if (data.config && typeof data.config === "object") {
3981
+ store.setState((prev) => ({ ...prev, ...data.config }));
3975
3982
  }
3976
3983
  });
3977
3984
  };
3978
- const fetchScriptSettings = async () => {
3985
+ const fetchScriptConfig = async () => {
3979
3986
  try {
3980
- const response = await fetchNui("GET_FULL_SCRIPT_SETTINGS");
3981
- if (response?.success && response.data?.settings) {
3982
- store.setState(() => response.data.settings);
3987
+ const response = await fetchNui("GET_FULL_SCRIPT_CONFIG");
3988
+ if (response?.success && response.data?.config) {
3989
+ store.setState(() => response.data.config);
3983
3990
  if (typeof response.data.clientVersion === "number") {
3984
3991
  clientVersion = response.data.clientVersion;
3985
3992
  }
3986
- return response.data.settings;
3993
+ return response.data.config;
3987
3994
  }
3988
3995
  } catch {
3989
3996
  }
3990
3997
  return null;
3991
3998
  };
3992
- const updateScriptSettings = async (newSettings) => {
3993
- store.setState((prev) => ({ ...prev, ...newSettings }));
3994
- const response = await fetchNui("UPDATE_SCRIPT_SETTINGS", {
3995
- data: newSettings,
3999
+ const updateScriptConfig = async (newConfig) => {
4000
+ store.setState((prev) => ({ ...prev, ...newConfig }));
4001
+ const response = await fetchNui("UPDATE_SCRIPT_CONFIG", {
4002
+ data: newConfig,
3996
4003
  expectedVersion: clientVersion
3997
4004
  });
3998
4005
  if (response?.meta?.client_version != null) {
@@ -4003,18 +4010,29 @@ function createScriptSettings(defaultValue) {
4003
4010
  }
4004
4011
  return response;
4005
4012
  };
4006
- const getScriptSettingsHistory = async (params = {}) => {
4007
- return fetchNui("GET_SCRIPT_SETTINGS_HISTORY", params);
4013
+ const getScriptConfigHistory = async (params = {}) => {
4014
+ return fetchNui("GET_SCRIPT_CONFIG_HISTORY", params);
4015
+ };
4016
+ const resetConfig = async () => {
4017
+ const response = await fetchNui("RESET_SCRIPT_CONFIG");
4018
+ if (response?.success) {
4019
+ const fresh = await fetchScriptConfig();
4020
+ if (fresh) {
4021
+ store.setState(() => fresh);
4022
+ }
4023
+ }
4024
+ return response;
4008
4025
  };
4009
4026
  _instance = {
4010
4027
  store,
4011
- updateSettings: updateScriptSettings,
4012
- getHistory: getScriptSettingsHistory,
4013
- fetchSettings: fetchScriptSettings
4028
+ updateConfig: updateScriptConfig,
4029
+ resetConfig,
4030
+ getHistory: getScriptConfigHistory,
4031
+ fetchConfig: fetchScriptConfig
4014
4032
  };
4015
- return { store, updateScriptSettings, getScriptSettingsHistory, useScriptSettingHooks, fetchScriptSettings };
4033
+ return { store, updateScriptConfig, resetConfig, getScriptConfigHistory, useScriptConfigHooks, fetchScriptConfig };
4016
4034
  }
4017
- var settingsPanelQueryClient = new reactQuery.QueryClient({
4035
+ var configPanelQueryClient = new reactQuery.QueryClient({
4018
4036
  defaultOptions: { queries: { staleTime: 3e4, gcTime: 5 * 6e4 } }
4019
4037
  });
4020
4038
  function NavItemButton({
@@ -4058,15 +4076,15 @@ function NavItemButton({
4058
4076
  }
4059
4077
  );
4060
4078
  }
4061
- function SettingsJsonModal({
4079
+ function ConfigJsonModal({
4062
4080
  onClose,
4063
4081
  schema
4064
4082
  }) {
4065
4083
  const theme2 = core.useMantineTheme();
4066
4084
  const color = theme2.colors[theme2.primaryColor][5];
4067
4085
  const form = useForm();
4068
- const [json, setJson] = React4.useState(() => JSON.stringify(form.values, null, 2));
4069
- const [error2, setError] = React4.useState(null);
4086
+ const [json, setJson] = React5.useState(() => JSON.stringify(form.values, null, 2));
4087
+ const [error2, setError] = React5.useState(null);
4070
4088
  const handleSave = () => {
4071
4089
  try {
4072
4090
  const parsed = JSON.parse(json);
@@ -4095,7 +4113,7 @@ function SettingsJsonModal({
4095
4113
  setError(e.message);
4096
4114
  }
4097
4115
  };
4098
- return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "Settings JSON", icon: lucideReact.Code2, iconColor: color, onClose, width: "60vh", maxHeight: "80vh", zIndex: 200, children: [
4116
+ return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "Config JSON", icon: lucideReact.Code2, iconColor: color, onClose, width: "60vh", maxHeight: "80vh", zIndex: 200, children: [
4099
4117
  /* @__PURE__ */ jsxRuntime.jsxs(core.Box, { flex: 1, p: "0.8vh", style: { overflowY: "auto" }, children: [
4100
4118
  /* @__PURE__ */ jsxRuntime.jsx(
4101
4119
  core.JsonInput,
@@ -4237,22 +4255,22 @@ function HistoryTableHeader() {
4237
4255
  /* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: "Version" })
4238
4256
  ] });
4239
4257
  }
4240
- function SettingsHistoryModal({
4258
+ function ConfigHistoryModal({
4241
4259
  onClose
4242
4260
  }) {
4243
- const { getHistory } = getScriptSettingsInstance();
4261
+ const { getHistory } = getScriptConfigInstance();
4244
4262
  const theme2 = core.useMantineTheme();
4245
4263
  const color = theme2.colors[theme2.primaryColor][5];
4246
- const [queryInput, setQueryInput] = React4.useState("");
4247
- const [pathInput, setPathInput] = React4.useState("");
4248
- const [adminInput, setAdminInput] = React4.useState("");
4249
- const [query, setQuery] = React4.useState("");
4250
- const [path, setPath] = React4.useState("");
4251
- const [admin, setAdmin] = React4.useState("");
4252
- const [expandedKey, setExpandedKey] = React4.useState(null);
4253
- const filters = React4.useMemo(() => ({ query, path, admin }), [query, path, admin]);
4264
+ const [queryInput, setQueryInput] = React5.useState("");
4265
+ const [pathInput, setPathInput] = React5.useState("");
4266
+ const [adminInput, setAdminInput] = React5.useState("");
4267
+ const [query, setQuery] = React5.useState("");
4268
+ const [path, setPath] = React5.useState("");
4269
+ const [admin, setAdmin] = React5.useState("");
4270
+ const [expandedKey, setExpandedKey] = React5.useState(null);
4271
+ const filters = React5.useMemo(() => ({ query, path, admin }), [query, path, admin]);
4254
4272
  const historyQuery = reactQuery.useInfiniteQuery({
4255
- queryKey: ["scriptSettingsHistory", filters],
4273
+ queryKey: ["scriptConfigHistory", filters],
4256
4274
  initialPageParam: 0,
4257
4275
  queryFn: async ({ pageParam }) => {
4258
4276
  const response = await getHistory({
@@ -4263,7 +4281,7 @@ function SettingsHistoryModal({
4263
4281
  admin: filters.admin || void 0
4264
4282
  });
4265
4283
  if (!response?.success || !response.data) {
4266
- throw new Error(response?._error || "Failed to load settings history");
4284
+ throw new Error(response?._error || "Failed to load config history");
4267
4285
  }
4268
4286
  return response.data;
4269
4287
  },
@@ -4277,7 +4295,7 @@ function SettingsHistoryModal({
4277
4295
  historyQuery.fetchNextPage();
4278
4296
  }
4279
4297
  };
4280
- return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "Settings History", icon: lucideReact.History, iconColor: color, onClose, width: "88vh", maxHeight: "82vh", zIndex: 260, children: [
4298
+ return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "Config History", icon: lucideReact.History, iconColor: color, onClose, width: "88vh", maxHeight: "82vh", zIndex: 260, children: [
4281
4299
  /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { flex: 1, minHeight: 0 }, children: [
4282
4300
  /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { gap: "xs", p: "sm", style: { borderBottom: `0.1vh solid ${core.alpha(theme2.colors.dark[7], 0.8)}` }, children: [
4283
4301
  /* @__PURE__ */ jsxRuntime.jsx(core.TextInput, { leftSection: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { size: "1.4vh" }), placeholder: "Search path/admin/value", value: queryInput, onChange: (e) => setQueryInput(e.currentTarget.value), size: "xs", style: { flex: 1 } }),
@@ -4326,7 +4344,7 @@ function SettingsHistoryModal({
4326
4344
  ) })
4327
4345
  ] });
4328
4346
  }
4329
- function SettingsPanelInner({
4347
+ function ConfigPanelInner({
4330
4348
  navItems,
4331
4349
  title,
4332
4350
  subtitle,
@@ -4335,28 +4353,37 @@ function SettingsPanelInner({
4335
4353
  onClose,
4336
4354
  schema,
4337
4355
  resetConfirmText,
4338
- defaultSettings,
4356
+ defaultConfig,
4339
4357
  width,
4340
4358
  height
4341
4359
  }) {
4342
- const { updateSettings, getHistory } = getScriptSettingsInstance();
4360
+ const { updateConfig, resetConfig, getHistory } = getScriptConfigInstance();
4343
4361
  const form = useForm();
4344
4362
  const theme2 = core.useMantineTheme();
4345
4363
  const color = theme2.colors[theme2.primaryColor][5];
4346
4364
  const version = useSettings((s) => s.resourceVersion);
4347
- const [activeTab, setActiveTab] = React4.useState(navItems[0]?.id ?? "");
4348
- const [jsonOpen, setJsonOpen] = React4.useState(false);
4349
- const [historyOpen, setHistoryOpen] = React4.useState(false);
4350
- const [resetOpen, setResetOpen] = React4.useState(false);
4351
- const [closeConfirmOpen, setCloseConfirmOpen] = React4.useState(false);
4365
+ const [activeTab, setActiveTab] = React5.useState(navItems[0]?.id ?? "");
4366
+ const firstMountRef = React5.useRef(true);
4367
+ const [jsonOpen, setJsonOpen] = React5.useState(false);
4368
+ const [historyOpen, setHistoryOpen] = React5.useState(false);
4369
+ const [resetOpen, setResetOpen] = React5.useState(false);
4370
+ const [pendingAction, setPendingAction] = React5.useState(null);
4352
4371
  const changedCount = form.changedCount ?? 0;
4353
4372
  const isDirty = changedCount > 0;
4354
- React4.useEffect(() => {
4373
+ const goBack = () => fetchNui("CONFIG_PANEL_BACK");
4374
+ const handleBack = () => {
4375
+ if (isDirty) {
4376
+ setPendingAction("back");
4377
+ return;
4378
+ }
4379
+ goBack();
4380
+ };
4381
+ React5.useEffect(() => {
4355
4382
  function handleKeyDown(e) {
4356
4383
  if (e.key !== "Escape") return;
4357
4384
  if (isDirty) {
4358
4385
  e.preventDefault();
4359
- setCloseConfirmOpen(true);
4386
+ setPendingAction("close");
4360
4387
  return;
4361
4388
  }
4362
4389
  onClose();
@@ -4365,34 +4392,40 @@ function SettingsPanelInner({
4365
4392
  return () => window.removeEventListener("keydown", handleKeyDown);
4366
4393
  }, [isDirty, onClose]);
4367
4394
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4368
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsxRuntime.jsx(SettingsJsonModal, { onClose: () => setJsonOpen(false), schema }) }),
4369
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsxRuntime.jsx(SettingsHistoryModal, { onClose: () => setHistoryOpen(false) }) }),
4395
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsxRuntime.jsx(ConfigJsonModal, { onClose: () => setJsonOpen(false), schema }) }),
4396
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsxRuntime.jsx(ConfigHistoryModal, { onClose: () => setHistoryOpen(false) }) }),
4370
4397
  /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: resetOpen && /* @__PURE__ */ jsxRuntime.jsx(
4371
4398
  ConfirmModal,
4372
4399
  {
4373
4400
  title: "Reset to Defaults",
4374
- description: "This will permanently reset ALL settings back to their defaults. Every setting you have configured will be overwritten. This cannot be undone.",
4375
- confirmLabel: "Reset Settings",
4401
+ description: "This will permanently reset ALL config back to the defaults. Every value you have configured will be overwritten. This cannot be undone.",
4402
+ confirmLabel: "Reset Config",
4376
4403
  confirmText: resetConfirmText,
4377
- onConfirm: () => {
4378
- updateSettings(defaultSettings).then(() => form.reinitialize(cloneSettings(defaultSettings)));
4404
+ onConfirm: async () => {
4379
4405
  setResetOpen(false);
4406
+ const result = await resetConfig();
4407
+ if (result?.success) {
4408
+ const { store } = getScriptConfigInstance();
4409
+ form.reinitialize(cloneConfig(store.getState()));
4410
+ }
4380
4411
  },
4381
4412
  onClose: () => setResetOpen(false),
4382
4413
  zIndex: 300
4383
4414
  }
4384
4415
  ) }),
4385
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: closeConfirmOpen && /* @__PURE__ */ jsxRuntime.jsx(
4416
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: pendingAction !== null && /* @__PURE__ */ jsxRuntime.jsx(
4386
4417
  ConfirmModal,
4387
4418
  {
4388
4419
  title: "Discard Unsaved Changes?",
4389
- description: "You have unsaved changes. Closing now will discard them.",
4390
- confirmLabel: "Close Without Saving",
4420
+ description: pendingAction === "back" ? "You have unsaved changes. Going back now will discard them." : "You have unsaved changes. Closing now will discard them.",
4421
+ confirmLabel: pendingAction === "back" ? "Go Back Without Saving" : "Close Without Saving",
4391
4422
  onConfirm: () => {
4392
- setCloseConfirmOpen(false);
4393
- onClose();
4423
+ const action = pendingAction;
4424
+ setPendingAction(null);
4425
+ if (action === "back") goBack();
4426
+ else onClose();
4394
4427
  },
4395
- onClose: () => setCloseConfirmOpen(false),
4428
+ onClose: () => setPendingAction(null),
4396
4429
  zIndex: 300
4397
4430
  }
4398
4431
  ) }),
@@ -4419,9 +4452,33 @@ function SettingsPanelInner({
4419
4452
  exit: { scale: 0.3, opacity: 0, transform: "translate(-50%, -50%)" },
4420
4453
  children: [
4421
4454
  /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { width: "18vh", flexShrink: 0, borderRight: `0.1vh solid ${core.alpha(theme2.colors.dark[6], 0.8)}`, background: core.alpha(theme2.colors.dark[8], 0.6), overflow: "hidden" }, children: [
4422
- /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "baseline", gap: "0.3vh", px: "sm", py: "sm", style: { borderBottom: `0.1vh solid ${core.alpha(theme2.colors.dark[6], 0.5)}`, flexShrink: 0 }, children: [
4423
- /* @__PURE__ */ jsxRuntime.jsx(core.Text, { size: "lg", ff: "Akrobat Bold", tt: "uppercase", children: title }),
4424
- subtitle && /* @__PURE__ */ jsxRuntime.jsx(core.Text, { tt: "uppercase", fw: 600, c: color, children: subtitle })
4455
+ /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "0.6vh", px: "sm", py: "sm", style: { borderBottom: `0.1vh solid ${core.alpha(theme2.colors.dark[6], 0.5)}`, flexShrink: 0 }, children: [
4456
+ /* @__PURE__ */ jsxRuntime.jsx(
4457
+ framerMotion.motion.button,
4458
+ {
4459
+ title: "Back to script list",
4460
+ onClick: handleBack,
4461
+ whileHover: { background: core.alpha(color, 0.16), borderColor: core.alpha(color, 0.45) },
4462
+ whileTap: { scale: 0.95 },
4463
+ style: {
4464
+ aspectRatio: "1 / 1",
4465
+ height: "2.4vh",
4466
+ background: core.alpha(color, 0.08),
4467
+ border: `0.1vh solid ${core.alpha(color, 0.3)}`,
4468
+ borderRadius: theme2.radius.xs,
4469
+ cursor: "pointer",
4470
+ display: "flex",
4471
+ alignItems: "center",
4472
+ justifyContent: "center",
4473
+ flexShrink: 0
4474
+ },
4475
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { size: "1.4vh", color })
4476
+ }
4477
+ ),
4478
+ /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { minWidth: 0, lineHeight: 1 }, children: [
4479
+ /* @__PURE__ */ jsxRuntime.jsx(core.Text, { size: "lg", ff: "Akrobat Bold", tt: "uppercase", lts: "0.04em", truncate: true, children: title }),
4480
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.08em", c: color, truncate: true, children: subtitle })
4481
+ ] })
4425
4482
  ] }),
4426
4483
  /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { gap: "xxs", px: "xs", py: "xs", style: { borderBottom: `0.1vh solid ${core.alpha(theme2.colors.dark[6], 0.4)}`, flexShrink: 0 }, children: [
4427
4484
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -4524,7 +4581,7 @@ function SettingsPanelInner({
4524
4581
  /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsxRuntime.jsx(
4525
4582
  framerMotion.motion.div,
4526
4583
  {
4527
- initial: { opacity: 0, y: 4 },
4584
+ initial: firstMountRef.current ? (firstMountRef.current = false, false) : { opacity: 0, y: 4 },
4528
4585
  animate: { opacity: 1, y: 0 },
4529
4586
  exit: { opacity: 0, y: -4 },
4530
4587
  transition: { duration: 0.15 },
@@ -4538,15 +4595,15 @@ function SettingsPanelInner({
4538
4595
  )
4539
4596
  ] });
4540
4597
  }
4541
- function cloneSettings(value) {
4598
+ function cloneConfig(value) {
4542
4599
  return JSON.parse(JSON.stringify(value));
4543
4600
  }
4544
4601
  function ServerOnlyFetcher() {
4545
- const { fetchSettings } = getScriptSettingsInstance();
4602
+ const { fetchConfig } = getScriptConfigInstance();
4546
4603
  const { reinitialize } = useFormActions();
4547
- React4.useEffect(() => {
4604
+ React5.useEffect(() => {
4548
4605
  let cancelled = false;
4549
- fetchSettings().then((full) => {
4606
+ fetchConfig().then((full) => {
4550
4607
  if (!cancelled && full) reinitialize(full);
4551
4608
  }).catch(() => {
4552
4609
  });
@@ -4557,28 +4614,28 @@ function ServerOnlyFetcher() {
4557
4614
  return null;
4558
4615
  }
4559
4616
  var defaultOnClose = () => fetchNui("CLOSE_ADMIN_SECTION");
4560
- function SettingsPanel(props) {
4617
+ function ConfigPanel(props) {
4561
4618
  const { open, onClose = defaultOnClose } = props;
4562
- const { store, updateSettings, fetchSettings } = getScriptSettingsInstance();
4563
- const [isSaving, setIsSaving] = React4.useState(false);
4619
+ const { store, updateConfig } = getScriptConfigInstance();
4620
+ const [isSaving, setIsSaving] = React5.useState(false);
4564
4621
  if (!open) return null;
4565
- return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: settingsPanelQueryClient, children: /* @__PURE__ */ jsxRuntime.jsxs(
4622
+ return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: configPanelQueryClient, children: /* @__PURE__ */ jsxRuntime.jsxs(
4566
4623
  FormProvider,
4567
4624
  {
4568
- initialValues: cloneSettings(store.getState()),
4625
+ initialValues: cloneConfig(store.getState()),
4569
4626
  onSubmit: async (form) => {
4570
4627
  if (isSaving) return;
4571
4628
  setIsSaving(true);
4572
4629
  try {
4573
- const result = await updateSettings(form.values);
4630
+ const result = await updateConfig(form.values);
4574
4631
  if (result?.success) {
4575
- form.reinitialize(cloneSettings(form.values));
4576
- settingsPanelQueryClient.invalidateQueries({ queryKey: ["scriptSettingsHistory"] });
4632
+ form.reinitialize(cloneConfig(form.values));
4633
+ configPanelQueryClient.invalidateQueries({ queryKey: ["scriptConfigHistory"] });
4577
4634
  return;
4578
4635
  }
4579
- form.reinitialize(cloneSettings(store.getState()));
4636
+ form.reinitialize(cloneConfig(store.getState()));
4580
4637
  if (result?._error) {
4581
- console.warn(`[SettingsPanel] settings save failed: ${result._error}`);
4638
+ console.warn(`[ConfigPanel] config save failed: ${result._error}`);
4582
4639
  }
4583
4640
  } finally {
4584
4641
  setIsSaving(false);
@@ -4587,7 +4644,7 @@ function SettingsPanel(props) {
4587
4644
  children: [
4588
4645
  /* @__PURE__ */ jsxRuntime.jsx(ServerOnlyFetcher, {}),
4589
4646
  /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: open && /* @__PURE__ */ jsxRuntime.jsx(
4590
- SettingsPanelInner,
4647
+ ConfigPanelInner,
4591
4648
  {
4592
4649
  ...props,
4593
4650
  onClose,
@@ -4599,9 +4656,9 @@ function SettingsPanel(props) {
4599
4656
  ) });
4600
4657
  }
4601
4658
  function LazyImage({ src, alt, style }) {
4602
- const [visible, setVisible] = React4.useState(false);
4603
- const ref = React4.useRef(null);
4604
- React4.useEffect(() => {
4659
+ const [visible, setVisible] = React5.useState(false);
4660
+ const ref = React5.useRef(null);
4661
+ React5.useEffect(() => {
4605
4662
  const observer = new IntersectionObserver(([entry]) => {
4606
4663
  if (entry.isIntersecting) {
4607
4664
  setVisible(true);
@@ -4615,7 +4672,7 @@ function LazyImage({ src, alt, style }) {
4615
4672
  }
4616
4673
  function SelectItem(props) {
4617
4674
  const invItems = useItems();
4618
- const formattedItems = React4.useMemo(() => {
4675
+ const formattedItems = React5.useMemo(() => {
4619
4676
  const seen = /* @__PURE__ */ new Set();
4620
4677
  return useItemsList(props.excludeItemNames ?? []).filter((item) => {
4621
4678
  if (seen.has(item.name)) return false;
@@ -4667,9 +4724,9 @@ function SelectItem(props) {
4667
4724
  }
4668
4725
  );
4669
4726
  }
4670
- var KeyBindContext = React4.createContext(null);
4727
+ var KeyBindContext = React5.createContext(null);
4671
4728
  function useKeyBindContext() {
4672
- const ctx = React4.useContext(KeyBindContext);
4729
+ const ctx = React5.useContext(KeyBindContext);
4673
4730
  if (!ctx) {
4674
4731
  throw new Error("FiveMKeyBindInput.* must be used inside <FiveMKeyBindInput>");
4675
4732
  }
@@ -4748,7 +4805,7 @@ function AsyncSaveButton({
4748
4805
  style
4749
4806
  }) {
4750
4807
  const theme2 = core.useMantineTheme();
4751
- const [state, setState] = React4.useState("idle");
4808
+ const [state, setState] = React5.useState("idle");
4752
4809
  const handleClick = async () => {
4753
4810
  if (state === "pending") return;
4754
4811
  setState("pending");
@@ -4795,6 +4852,160 @@ function AdminPageTitle(props) {
4795
4852
  /* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", tt: "uppercase", lts: "0.1em", size: "sm", c: "rgba(255,255,255,0.6)", children: locale(props.title) })
4796
4853
  ] });
4797
4854
  }
4855
+ var loadPersistedState = (storageKey) => {
4856
+ try {
4857
+ const raw = localStorage.getItem(storageKey);
4858
+ return raw ? JSON.parse(raw) : {};
4859
+ } catch {
4860
+ return {};
4861
+ }
4862
+ };
4863
+ var savePersistedState = (storageKey, state) => {
4864
+ try {
4865
+ localStorage.setItem(storageKey, JSON.stringify(state));
4866
+ } catch {
4867
+ }
4868
+ };
4869
+ function TestBed({
4870
+ items,
4871
+ storageKey = "testbed:open-state",
4872
+ disablePersistence = false,
4873
+ title = "TestBed"
4874
+ }) {
4875
+ const [open, setOpen] = React5.useState(false);
4876
+ const itemsRef = React5.useRef(items);
4877
+ itemsRef.current = items;
4878
+ React5.useEffect(() => {
4879
+ if (!isEnvBrowser() || disablePersistence) return;
4880
+ const persisted = loadPersistedState(storageKey);
4881
+ itemsRef.current.forEach((item) => {
4882
+ const persistedValue = persisted[item.key];
4883
+ if (typeof persistedValue === "boolean" && persistedValue !== item.active) {
4884
+ item.onToggle(persistedValue);
4885
+ }
4886
+ });
4887
+ }, []);
4888
+ if (!isEnvBrowser()) return null;
4889
+ const toggle = (item) => {
4890
+ const next = !item.active;
4891
+ item.onToggle(next);
4892
+ if (!disablePersistence) {
4893
+ const persisted = loadPersistedState(storageKey);
4894
+ persisted[item.key] = next;
4895
+ savePersistedState(storageKey, persisted);
4896
+ }
4897
+ };
4898
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4899
+ "div",
4900
+ {
4901
+ style: {
4902
+ position: "fixed",
4903
+ top: "1vh",
4904
+ left: "1vh",
4905
+ zIndex: 2147483647,
4906
+ pointerEvents: "auto",
4907
+ fontSize: "1.4vh"
4908
+ },
4909
+ children: [
4910
+ /* @__PURE__ */ jsxRuntime.jsxs(
4911
+ core.Flex,
4912
+ {
4913
+ align: "center",
4914
+ gap: "xs",
4915
+ px: "sm",
4916
+ py: "xs",
4917
+ onClick: () => setOpen((v) => !v),
4918
+ style: {
4919
+ cursor: "pointer",
4920
+ background: "rgba(0,0,0,0.55)",
4921
+ backdropFilter: "blur(0.6vh)",
4922
+ WebkitBackdropFilter: "blur(0.6vh)",
4923
+ border: "0.1vh solid rgba(255,255,255,0.1)",
4924
+ borderRadius: "var(--mantine-radius-sm)",
4925
+ userSelect: "none",
4926
+ minWidth: "16vh"
4927
+ },
4928
+ children: [
4929
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FlaskConical, { size: 14, color: "rgba(255,255,255,0.7)" }),
4930
+ /* @__PURE__ */ jsxRuntime.jsx(
4931
+ core.Text,
4932
+ {
4933
+ size: "xs",
4934
+ ff: "Akrobat Bold",
4935
+ tt: "uppercase",
4936
+ lts: "0.08em",
4937
+ c: "rgba(255,255,255,0.85)",
4938
+ style: { flex: 1 },
4939
+ children: title
4940
+ }
4941
+ ),
4942
+ /* @__PURE__ */ jsxRuntime.jsx(core.ActionIcon, { size: "xs", variant: "transparent", c: "rgba(255,255,255,0.6)", children: open ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { size: 14 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 14 }) })
4943
+ ]
4944
+ }
4945
+ ),
4946
+ open && /* @__PURE__ */ jsxRuntime.jsx(
4947
+ core.Stack,
4948
+ {
4949
+ gap: 4,
4950
+ mt: "xxs",
4951
+ p: "xs",
4952
+ style: {
4953
+ background: "rgba(0,0,0,0.55)",
4954
+ backdropFilter: "blur(0.6vh)",
4955
+ WebkitBackdropFilter: "blur(0.6vh)",
4956
+ border: "0.1vh solid rgba(255,255,255,0.1)",
4957
+ borderRadius: "var(--mantine-radius-sm)",
4958
+ minWidth: "16vh",
4959
+ maxHeight: "80vh",
4960
+ overflowY: "auto"
4961
+ },
4962
+ children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
4963
+ core.Flex,
4964
+ {
4965
+ align: "center",
4966
+ justify: "space-between",
4967
+ gap: "xs",
4968
+ px: "xs",
4969
+ py: "xxs",
4970
+ onClick: () => toggle(item),
4971
+ style: {
4972
+ cursor: "pointer",
4973
+ borderRadius: "var(--mantine-radius-xs)",
4974
+ background: item.active ? "rgba(245,158,11,0.15)" : "rgba(255,255,255,0.03)",
4975
+ border: `0.1vh solid ${item.active ? "rgba(245,158,11,0.35)" : "rgba(255,255,255,0.05)"}`,
4976
+ userSelect: "none"
4977
+ },
4978
+ children: [
4979
+ /* @__PURE__ */ jsxRuntime.jsx(
4980
+ core.Text,
4981
+ {
4982
+ size: "xs",
4983
+ ff: "Akrobat Bold",
4984
+ c: item.active ? "#f59e0b" : "rgba(255,255,255,0.75)",
4985
+ children: item.label
4986
+ }
4987
+ ),
4988
+ /* @__PURE__ */ jsxRuntime.jsx(
4989
+ core.Text,
4990
+ {
4991
+ size: "xxs",
4992
+ ff: "Akrobat Bold",
4993
+ tt: "uppercase",
4994
+ lts: "0.06em",
4995
+ c: item.active ? "#f59e0b" : "rgba(255,255,255,0.35)",
4996
+ children: item.active ? "On" : "Off"
4997
+ }
4998
+ )
4999
+ ]
5000
+ },
5001
+ item.key
5002
+ ))
5003
+ }
5004
+ )
5005
+ ]
5006
+ }
5007
+ );
5008
+ }
4798
5009
  function useTornEdges() {
4799
5010
  const game = useSettings((state) => state.game);
4800
5011
  return game === "rdr3" ? "torn-edge-wrapper" : "";
@@ -4985,7 +5196,7 @@ function mergeMantineThemeSafe(base, custom, override) {
4985
5196
  }
4986
5197
  };
4987
5198
  }
4988
- var DirkErrorBoundary = class extends React4__default.default.Component {
5199
+ var DirkErrorBoundary = class extends React5__default.default.Component {
4989
5200
  constructor() {
4990
5201
  super(...arguments);
4991
5202
  __publicField(this, "state", { error: null, stack: void 0 });
@@ -5048,12 +5259,12 @@ function DirkProvider({ children, overideResourceName, themeOverride }) {
5048
5259
  customTheme,
5049
5260
  game
5050
5261
  } = useSettings();
5051
- React4.useLayoutEffect(() => {
5262
+ React5.useLayoutEffect(() => {
5052
5263
  useSettings.setState({
5053
5264
  overideResourceName
5054
5265
  });
5055
5266
  }, [overideResourceName]);
5056
- React4.useEffect(() => {
5267
+ React5.useEffect(() => {
5057
5268
  fetchNui("NUI_READY").catch(() => {
5058
5269
  });
5059
5270
  Promise.all([
@@ -5068,7 +5279,7 @@ function DirkProvider({ children, overideResourceName, themeOverride }) {
5068
5279
  console.error("Failed to fetch initial settings within dirk-cfx-react:", err);
5069
5280
  });
5070
5281
  }, []);
5071
- const mergedTheme = React4.useMemo(
5282
+ const mergedTheme = React5.useMemo(
5072
5283
  () => mergeMantineThemeSafe(
5073
5284
  { ...theme_default, primaryColor, primaryShade },
5074
5285
  customTheme,
@@ -5076,7 +5287,7 @@ function DirkProvider({ children, overideResourceName, themeOverride }) {
5076
5287
  ),
5077
5288
  [primaryColor, primaryShade, customTheme, themeOverride]
5078
5289
  );
5079
- React4.useEffect(() => {
5290
+ React5.useEffect(() => {
5080
5291
  document.body.style.fontFamily = game === "rdr3" ? '"Red Dead", sans-serif' : '"Akrobat Regular", sans-serif';
5081
5292
  }, [game]);
5082
5293
  const content = isEnvBrowser() ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -5096,6 +5307,7 @@ exports.AsyncSaveButton = AsyncSaveButton;
5096
5307
  exports.BlipColorSelect = BlipColorSelect;
5097
5308
  exports.BlipIconSelect = BlipIconSelect;
5098
5309
  exports.BorderedIcon = BorderedIcon;
5310
+ exports.ConfigPanel = ConfigPanel;
5099
5311
  exports.ConfirmModal = ConfirmModal;
5100
5312
  exports.Counter = Counter;
5101
5313
  exports.DirkProvider = DirkProvider;
@@ -5122,13 +5334,13 @@ exports.PromptModal = PromptModal;
5122
5334
  exports.SegmentedControl = SegmentedControl;
5123
5335
  exports.SegmentedProgress = SegmentedProgress;
5124
5336
  exports.SelectItem = SelectItem;
5125
- exports.SettingsPanel = SettingsPanel;
5337
+ exports.TestBed = TestBed;
5126
5338
  exports.Title = Title;
5127
5339
  exports.TornEdgeSVGFilter = TornEdgeSVGFilter;
5128
5340
  exports.colorWithAlpha = colorWithAlpha;
5129
5341
  exports.copyToClipboard = copyToClipboard;
5130
5342
  exports.createFormStore = createFormStore;
5131
- exports.createScriptSettings = createScriptSettings;
5343
+ exports.createScriptConfig = createScriptConfig;
5132
5344
  exports.createSkill = createSkill;
5133
5345
  exports.extractDefaults = extractDefaults;
5134
5346
  exports.fetchLuaTable = fetchLuaTable;
@@ -5136,7 +5348,7 @@ exports.fetchNui = fetchNui;
5136
5348
  exports.gameToMap = gameToMap;
5137
5349
  exports.getImageShape = getImageShape;
5138
5350
  exports.getItemImageUrl = getItemImageUrl;
5139
- exports.getScriptSettingsInstance = getScriptSettingsInstance;
5351
+ exports.getScriptConfigInstance = getScriptConfigInstance;
5140
5352
  exports.initialFetches = initialFetches;
5141
5353
  exports.internalEvent = internalEvent;
5142
5354
  exports.isEnvBrowser = isEnvBrowser;