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.
@@ -1,4 +1,4 @@
1
- import { Flex, Text, Image, TextInput, Select, Box, useMantineTheme, alpha, Progress, RingProgress, Portal, Button, Loader, Group, JsonInput } from '@mantine/core';
1
+ import { Flex, Text, Image, TextInput, Select, Box, useMantineTheme, alpha, Progress, RingProgress, Portal, Button, 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';
@@ -6,7 +6,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
6
6
  import { motion, AnimatePresence, useMotionValue } from 'framer-motion';
7
7
  import clickSoundUrl from '../click_sound-PNCRRTM4.mp3';
8
8
  import hoverSoundUrl from '../hover_sound-NBUA222C.mp3';
9
- import { X, AlertTriangle, Trash2, Check, Undo2, Redo2, Save, History, XCircle, Code2, RotateCcw, Search, Filter, User, ChevronDown } from 'lucide-react';
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
@@ -1292,6 +1292,7 @@ var localeStore = create((set, get) => {
1292
1292
  var locale = localeStore.getState().locale;
1293
1293
  registerInitialFetch("GET_LOCALES", void 0).then((data) => {
1294
1294
  localeStore.setState({ locales: data });
1295
+ }).catch(() => {
1295
1296
  });
1296
1297
  var useItems = create(() => ({}));
1297
1298
  var useItemsList = (excludeItemNames = []) => {
@@ -1305,6 +1306,7 @@ registerInitialFetch("FETCH_ALL_ITEMS", null, {
1305
1306
  }).then((fetchedItems) => {
1306
1307
  if (!fetchedItems) return;
1307
1308
  useItems.setState(fetchedItems);
1309
+ }).catch(() => {
1308
1310
  });
1309
1311
 
1310
1312
  // src/utils/inputMapper.ts
@@ -2541,6 +2543,7 @@ function Modal({
2541
2543
  children
2542
2544
  }) {
2543
2545
  const theme = useMantineTheme();
2546
+ const pointerDownOnOverlay = useRef(false);
2544
2547
  return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(
2545
2548
  motion.div,
2546
2549
  {
@@ -2556,7 +2559,14 @@ function Modal({
2556
2559
  justifyContent: "center",
2557
2560
  background: "rgba(0,0,0,0.65)"
2558
2561
  },
2559
- onClick: clickOutside ? onClose : void 0,
2562
+ onPointerDown: (e) => {
2563
+ pointerDownOnOverlay.current = e.target === e.currentTarget;
2564
+ },
2565
+ onClick: (e) => {
2566
+ if (clickOutside && e.target === e.currentTarget && pointerDownOnOverlay.current) {
2567
+ onClose();
2568
+ }
2569
+ },
2560
2570
  children: /* @__PURE__ */ jsxs(
2561
2571
  motion.div,
2562
2572
  {
@@ -2564,7 +2574,6 @@ function Modal({
2564
2574
  animate: { opacity: 1, scale: 1, y: 0 },
2565
2575
  exit: { opacity: 0, scale: 0.96, y: 8 },
2566
2576
  transition: { duration: 0.18, ease: "easeOut" },
2567
- onClick: (e) => e.stopPropagation(),
2568
2577
  style: {
2569
2578
  background: alpha(theme.colors.dark[9], 0.98),
2570
2579
  border: `0.1vh solid ${theme.colors.dark[7]}`,
@@ -2661,7 +2670,7 @@ function Modal({
2661
2670
  children: description
2662
2671
  }
2663
2672
  ) }),
2664
- children
2673
+ /* @__PURE__ */ jsx("div", { style: { flex: 1, minHeight: 0, display: "flex", flexDirection: "column" }, children })
2665
2674
  ]
2666
2675
  }
2667
2676
  )
@@ -3284,10 +3293,10 @@ function useFormActions() {
3284
3293
  }
3285
3294
  return store.getState();
3286
3295
  }
3287
- function getScriptSettingsInstance() {
3288
- throw new Error("[dirk-cfx-react] createScriptSettings must be called before using SettingsPanel");
3296
+ function getScriptConfigInstance() {
3297
+ throw new Error("[dirk-cfx-react] createScriptConfig must be called before using ConfigPanel");
3289
3298
  }
3290
- var settingsPanelQueryClient = new QueryClient({
3299
+ var configPanelQueryClient = new QueryClient({
3291
3300
  defaultOptions: { queries: { staleTime: 3e4, gcTime: 5 * 6e4 } }
3292
3301
  });
3293
3302
  function NavItemButton({
@@ -3331,7 +3340,7 @@ function NavItemButton({
3331
3340
  }
3332
3341
  );
3333
3342
  }
3334
- function SettingsJsonModal({
3343
+ function ConfigJsonModal({
3335
3344
  onClose,
3336
3345
  schema
3337
3346
  }) {
@@ -3368,7 +3377,7 @@ function SettingsJsonModal({
3368
3377
  setError(e.message);
3369
3378
  }
3370
3379
  };
3371
- return /* @__PURE__ */ jsxs(Modal, { title: "Settings JSON", icon: Code2, iconColor: color, onClose, width: "60vh", maxHeight: "80vh", zIndex: 200, children: [
3380
+ return /* @__PURE__ */ jsxs(Modal, { title: "Config JSON", icon: Code2, iconColor: color, onClose, width: "60vh", maxHeight: "80vh", zIndex: 200, children: [
3372
3381
  /* @__PURE__ */ jsxs(Box, { flex: 1, p: "0.8vh", style: { overflowY: "auto" }, children: [
3373
3382
  /* @__PURE__ */ jsx(
3374
3383
  JsonInput,
@@ -3510,10 +3519,10 @@ function HistoryTableHeader() {
3510
3519
  /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: "Version" })
3511
3520
  ] });
3512
3521
  }
3513
- function SettingsHistoryModal({
3522
+ function ConfigHistoryModal({
3514
3523
  onClose
3515
3524
  }) {
3516
- const { getHistory } = getScriptSettingsInstance();
3525
+ const { getHistory } = getScriptConfigInstance();
3517
3526
  const theme = useMantineTheme();
3518
3527
  const color = theme.colors[theme.primaryColor][5];
3519
3528
  const [queryInput, setQueryInput] = useState("");
@@ -3525,7 +3534,7 @@ function SettingsHistoryModal({
3525
3534
  const [expandedKey, setExpandedKey] = useState(null);
3526
3535
  const filters = useMemo(() => ({ query, path, admin }), [query, path, admin]);
3527
3536
  const historyQuery = useInfiniteQuery({
3528
- queryKey: ["scriptSettingsHistory", filters],
3537
+ queryKey: ["scriptConfigHistory", filters],
3529
3538
  initialPageParam: 0,
3530
3539
  queryFn: async ({ pageParam }) => {
3531
3540
  const response = await getHistory({
@@ -3536,7 +3545,7 @@ function SettingsHistoryModal({
3536
3545
  admin: filters.admin || void 0
3537
3546
  });
3538
3547
  if (!response?.success || !response.data) {
3539
- throw new Error(response?._error || "Failed to load settings history");
3548
+ throw new Error(response?._error || "Failed to load config history");
3540
3549
  }
3541
3550
  return response.data;
3542
3551
  },
@@ -3550,7 +3559,7 @@ function SettingsHistoryModal({
3550
3559
  historyQuery.fetchNextPage();
3551
3560
  }
3552
3561
  };
3553
- return /* @__PURE__ */ jsxs(Modal, { title: "Settings History", icon: History, iconColor: color, onClose, width: "88vh", maxHeight: "82vh", zIndex: 260, children: [
3562
+ return /* @__PURE__ */ jsxs(Modal, { title: "Config History", icon: History, iconColor: color, onClose, width: "88vh", maxHeight: "82vh", zIndex: 260, children: [
3554
3563
  /* @__PURE__ */ jsxs(Flex, { direction: "column", style: { flex: 1, minHeight: 0 }, children: [
3555
3564
  /* @__PURE__ */ jsxs(Flex, { gap: "xs", p: "sm", style: { borderBottom: `0.1vh solid ${alpha(theme.colors.dark[7], 0.8)}` }, children: [
3556
3565
  /* @__PURE__ */ jsx(TextInput, { leftSection: /* @__PURE__ */ jsx(Search, { size: "1.4vh" }), placeholder: "Search path/admin/value", value: queryInput, onChange: (e) => setQueryInput(e.currentTarget.value), size: "xs", style: { flex: 1 } }),
@@ -3599,7 +3608,7 @@ function SettingsHistoryModal({
3599
3608
  ) })
3600
3609
  ] });
3601
3610
  }
3602
- function SettingsPanelInner({
3611
+ function ConfigPanelInner({
3603
3612
  navItems,
3604
3613
  title,
3605
3614
  subtitle,
@@ -3608,28 +3617,37 @@ function SettingsPanelInner({
3608
3617
  onClose,
3609
3618
  schema,
3610
3619
  resetConfirmText,
3611
- defaultSettings,
3620
+ defaultConfig,
3612
3621
  width,
3613
3622
  height
3614
3623
  }) {
3615
- const { updateSettings, getHistory } = getScriptSettingsInstance();
3624
+ const { updateConfig, resetConfig, getHistory } = getScriptConfigInstance();
3616
3625
  const form = useForm();
3617
3626
  const theme = useMantineTheme();
3618
3627
  const color = theme.colors[theme.primaryColor][5];
3619
3628
  const version = useSettings((s) => s.resourceVersion);
3620
3629
  const [activeTab, setActiveTab] = useState(navItems[0]?.id ?? "");
3630
+ const firstMountRef = useRef(true);
3621
3631
  const [jsonOpen, setJsonOpen] = useState(false);
3622
3632
  const [historyOpen, setHistoryOpen] = useState(false);
3623
3633
  const [resetOpen, setResetOpen] = useState(false);
3624
- const [closeConfirmOpen, setCloseConfirmOpen] = useState(false);
3634
+ const [pendingAction, setPendingAction] = useState(null);
3625
3635
  const changedCount = form.changedCount ?? 0;
3626
3636
  const isDirty = changedCount > 0;
3637
+ const goBack = () => fetchNui("CONFIG_PANEL_BACK");
3638
+ const handleBack = () => {
3639
+ if (isDirty) {
3640
+ setPendingAction("back");
3641
+ return;
3642
+ }
3643
+ goBack();
3644
+ };
3627
3645
  useEffect(() => {
3628
3646
  function handleKeyDown(e) {
3629
3647
  if (e.key !== "Escape") return;
3630
3648
  if (isDirty) {
3631
3649
  e.preventDefault();
3632
- setCloseConfirmOpen(true);
3650
+ setPendingAction("close");
3633
3651
  return;
3634
3652
  }
3635
3653
  onClose();
@@ -3638,34 +3656,40 @@ function SettingsPanelInner({
3638
3656
  return () => window.removeEventListener("keydown", handleKeyDown);
3639
3657
  }, [isDirty, onClose]);
3640
3658
  return /* @__PURE__ */ jsxs(Fragment, { children: [
3641
- /* @__PURE__ */ jsx(AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsx(SettingsJsonModal, { onClose: () => setJsonOpen(false), schema }) }),
3642
- /* @__PURE__ */ jsx(AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsx(SettingsHistoryModal, { onClose: () => setHistoryOpen(false) }) }),
3659
+ /* @__PURE__ */ jsx(AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsx(ConfigJsonModal, { onClose: () => setJsonOpen(false), schema }) }),
3660
+ /* @__PURE__ */ jsx(AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsx(ConfigHistoryModal, { onClose: () => setHistoryOpen(false) }) }),
3643
3661
  /* @__PURE__ */ jsx(AnimatePresence, { children: resetOpen && /* @__PURE__ */ jsx(
3644
3662
  ConfirmModal,
3645
3663
  {
3646
3664
  title: "Reset to Defaults",
3647
- description: "This will permanently reset ALL settings back to their defaults. Every setting you have configured will be overwritten. This cannot be undone.",
3648
- confirmLabel: "Reset Settings",
3665
+ description: "This will permanently reset ALL config back to the defaults. Every value you have configured will be overwritten. This cannot be undone.",
3666
+ confirmLabel: "Reset Config",
3649
3667
  confirmText: resetConfirmText,
3650
- onConfirm: () => {
3651
- updateSettings(defaultSettings).then(() => form.reinitialize(cloneSettings(defaultSettings)));
3668
+ onConfirm: async () => {
3652
3669
  setResetOpen(false);
3670
+ const result = await resetConfig();
3671
+ if (result?.success) {
3672
+ const { store } = getScriptConfigInstance();
3673
+ form.reinitialize(cloneConfig(store.getState()));
3674
+ }
3653
3675
  },
3654
3676
  onClose: () => setResetOpen(false),
3655
3677
  zIndex: 300
3656
3678
  }
3657
3679
  ) }),
3658
- /* @__PURE__ */ jsx(AnimatePresence, { children: closeConfirmOpen && /* @__PURE__ */ jsx(
3680
+ /* @__PURE__ */ jsx(AnimatePresence, { children: pendingAction !== null && /* @__PURE__ */ jsx(
3659
3681
  ConfirmModal,
3660
3682
  {
3661
3683
  title: "Discard Unsaved Changes?",
3662
- description: "You have unsaved changes. Closing now will discard them.",
3663
- confirmLabel: "Close Without Saving",
3684
+ description: pendingAction === "back" ? "You have unsaved changes. Going back now will discard them." : "You have unsaved changes. Closing now will discard them.",
3685
+ confirmLabel: pendingAction === "back" ? "Go Back Without Saving" : "Close Without Saving",
3664
3686
  onConfirm: () => {
3665
- setCloseConfirmOpen(false);
3666
- onClose();
3687
+ const action = pendingAction;
3688
+ setPendingAction(null);
3689
+ if (action === "back") goBack();
3690
+ else onClose();
3667
3691
  },
3668
- onClose: () => setCloseConfirmOpen(false),
3692
+ onClose: () => setPendingAction(null),
3669
3693
  zIndex: 300
3670
3694
  }
3671
3695
  ) }),
@@ -3692,9 +3716,33 @@ function SettingsPanelInner({
3692
3716
  exit: { scale: 0.3, opacity: 0, transform: "translate(-50%, -50%)" },
3693
3717
  children: [
3694
3718
  /* @__PURE__ */ jsxs(Flex, { direction: "column", style: { width: "18vh", flexShrink: 0, borderRight: `0.1vh solid ${alpha(theme.colors.dark[6], 0.8)}`, background: alpha(theme.colors.dark[8], 0.6), overflow: "hidden" }, children: [
3695
- /* @__PURE__ */ jsxs(Flex, { align: "baseline", gap: "0.3vh", px: "sm", py: "sm", style: { borderBottom: `0.1vh solid ${alpha(theme.colors.dark[6], 0.5)}`, flexShrink: 0 }, children: [
3696
- /* @__PURE__ */ jsx(Text, { size: "lg", ff: "Akrobat Bold", tt: "uppercase", children: title }),
3697
- subtitle && /* @__PURE__ */ jsx(Text, { tt: "uppercase", fw: 600, c: color, children: subtitle })
3719
+ /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "0.6vh", px: "sm", py: "sm", style: { borderBottom: `0.1vh solid ${alpha(theme.colors.dark[6], 0.5)}`, flexShrink: 0 }, children: [
3720
+ /* @__PURE__ */ jsx(
3721
+ motion.button,
3722
+ {
3723
+ title: "Back to script list",
3724
+ onClick: handleBack,
3725
+ whileHover: { background: alpha(color, 0.16), borderColor: alpha(color, 0.45) },
3726
+ whileTap: { scale: 0.95 },
3727
+ style: {
3728
+ aspectRatio: "1 / 1",
3729
+ height: "2.4vh",
3730
+ background: alpha(color, 0.08),
3731
+ border: `0.1vh solid ${alpha(color, 0.3)}`,
3732
+ borderRadius: theme.radius.xs,
3733
+ cursor: "pointer",
3734
+ display: "flex",
3735
+ alignItems: "center",
3736
+ justifyContent: "center",
3737
+ flexShrink: 0
3738
+ },
3739
+ children: /* @__PURE__ */ jsx(ArrowLeft, { size: "1.4vh", color })
3740
+ }
3741
+ ),
3742
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", style: { minWidth: 0, lineHeight: 1 }, children: [
3743
+ /* @__PURE__ */ jsx(Text, { size: "lg", ff: "Akrobat Bold", tt: "uppercase", lts: "0.04em", truncate: true, children: title }),
3744
+ subtitle && /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.08em", c: color, truncate: true, children: subtitle })
3745
+ ] })
3698
3746
  ] }),
3699
3747
  /* @__PURE__ */ jsxs(Flex, { gap: "xxs", px: "xs", py: "xs", style: { borderBottom: `0.1vh solid ${alpha(theme.colors.dark[6], 0.4)}`, flexShrink: 0 }, children: [
3700
3748
  /* @__PURE__ */ jsx(
@@ -3797,7 +3845,7 @@ function SettingsPanelInner({
3797
3845
  /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
3798
3846
  motion.div,
3799
3847
  {
3800
- initial: { opacity: 0, y: 4 },
3848
+ initial: firstMountRef.current ? (firstMountRef.current = false, false) : { opacity: 0, y: 4 },
3801
3849
  animate: { opacity: 1, y: 0 },
3802
3850
  exit: { opacity: 0, y: -4 },
3803
3851
  transition: { duration: 0.15 },
@@ -3811,15 +3859,15 @@ function SettingsPanelInner({
3811
3859
  )
3812
3860
  ] });
3813
3861
  }
3814
- function cloneSettings(value) {
3862
+ function cloneConfig(value) {
3815
3863
  return JSON.parse(JSON.stringify(value));
3816
3864
  }
3817
3865
  function ServerOnlyFetcher() {
3818
- const { fetchSettings } = getScriptSettingsInstance();
3866
+ const { fetchConfig } = getScriptConfigInstance();
3819
3867
  const { reinitialize } = useFormActions();
3820
3868
  useEffect(() => {
3821
3869
  let cancelled = false;
3822
- fetchSettings().then((full) => {
3870
+ fetchConfig().then((full) => {
3823
3871
  if (!cancelled && full) reinitialize(full);
3824
3872
  }).catch(() => {
3825
3873
  });
@@ -3830,28 +3878,28 @@ function ServerOnlyFetcher() {
3830
3878
  return null;
3831
3879
  }
3832
3880
  var defaultOnClose = () => fetchNui("CLOSE_ADMIN_SECTION");
3833
- function SettingsPanel(props) {
3881
+ function ConfigPanel(props) {
3834
3882
  const { open, onClose = defaultOnClose } = props;
3835
- const { store, updateSettings, fetchSettings } = getScriptSettingsInstance();
3883
+ const { store, updateConfig } = getScriptConfigInstance();
3836
3884
  const [isSaving, setIsSaving] = useState(false);
3837
3885
  if (!open) return null;
3838
- return /* @__PURE__ */ jsx(QueryClientProvider, { client: settingsPanelQueryClient, children: /* @__PURE__ */ jsxs(
3886
+ return /* @__PURE__ */ jsx(QueryClientProvider, { client: configPanelQueryClient, children: /* @__PURE__ */ jsxs(
3839
3887
  FormProvider,
3840
3888
  {
3841
- initialValues: cloneSettings(store.getState()),
3889
+ initialValues: cloneConfig(store.getState()),
3842
3890
  onSubmit: async (form) => {
3843
3891
  if (isSaving) return;
3844
3892
  setIsSaving(true);
3845
3893
  try {
3846
- const result = await updateSettings(form.values);
3894
+ const result = await updateConfig(form.values);
3847
3895
  if (result?.success) {
3848
- form.reinitialize(cloneSettings(form.values));
3849
- settingsPanelQueryClient.invalidateQueries({ queryKey: ["scriptSettingsHistory"] });
3896
+ form.reinitialize(cloneConfig(form.values));
3897
+ configPanelQueryClient.invalidateQueries({ queryKey: ["scriptConfigHistory"] });
3850
3898
  return;
3851
3899
  }
3852
- form.reinitialize(cloneSettings(store.getState()));
3900
+ form.reinitialize(cloneConfig(store.getState()));
3853
3901
  if (result?._error) {
3854
- console.warn(`[SettingsPanel] settings save failed: ${result._error}`);
3902
+ console.warn(`[ConfigPanel] config save failed: ${result._error}`);
3855
3903
  }
3856
3904
  } finally {
3857
3905
  setIsSaving(false);
@@ -3860,7 +3908,7 @@ function SettingsPanel(props) {
3860
3908
  children: [
3861
3909
  /* @__PURE__ */ jsx(ServerOnlyFetcher, {}),
3862
3910
  /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(
3863
- SettingsPanelInner,
3911
+ ConfigPanelInner,
3864
3912
  {
3865
3913
  ...props,
3866
3914
  onClose,
@@ -4068,7 +4116,161 @@ function AdminPageTitle(props) {
4068
4116
  /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", tt: "uppercase", lts: "0.1em", size: "sm", c: "rgba(255,255,255,0.6)", children: locale(props.title) })
4069
4117
  ] });
4070
4118
  }
4119
+ var loadPersistedState = (storageKey) => {
4120
+ try {
4121
+ const raw = localStorage.getItem(storageKey);
4122
+ return raw ? JSON.parse(raw) : {};
4123
+ } catch {
4124
+ return {};
4125
+ }
4126
+ };
4127
+ var savePersistedState = (storageKey, state) => {
4128
+ try {
4129
+ localStorage.setItem(storageKey, JSON.stringify(state));
4130
+ } catch {
4131
+ }
4132
+ };
4133
+ function TestBed({
4134
+ items,
4135
+ storageKey = "testbed:open-state",
4136
+ disablePersistence = false,
4137
+ title = "TestBed"
4138
+ }) {
4139
+ const [open, setOpen] = useState(false);
4140
+ const itemsRef = useRef(items);
4141
+ itemsRef.current = items;
4142
+ useEffect(() => {
4143
+ if (!isEnvBrowser() || disablePersistence) return;
4144
+ const persisted = loadPersistedState(storageKey);
4145
+ itemsRef.current.forEach((item) => {
4146
+ const persistedValue = persisted[item.key];
4147
+ if (typeof persistedValue === "boolean" && persistedValue !== item.active) {
4148
+ item.onToggle(persistedValue);
4149
+ }
4150
+ });
4151
+ }, []);
4152
+ if (!isEnvBrowser()) return null;
4153
+ const toggle = (item) => {
4154
+ const next = !item.active;
4155
+ item.onToggle(next);
4156
+ if (!disablePersistence) {
4157
+ const persisted = loadPersistedState(storageKey);
4158
+ persisted[item.key] = next;
4159
+ savePersistedState(storageKey, persisted);
4160
+ }
4161
+ };
4162
+ return /* @__PURE__ */ jsxs(
4163
+ "div",
4164
+ {
4165
+ style: {
4166
+ position: "fixed",
4167
+ top: "1vh",
4168
+ left: "1vh",
4169
+ zIndex: 2147483647,
4170
+ pointerEvents: "auto",
4171
+ fontSize: "1.4vh"
4172
+ },
4173
+ children: [
4174
+ /* @__PURE__ */ jsxs(
4175
+ Flex,
4176
+ {
4177
+ align: "center",
4178
+ gap: "xs",
4179
+ px: "sm",
4180
+ py: "xs",
4181
+ onClick: () => setOpen((v) => !v),
4182
+ style: {
4183
+ cursor: "pointer",
4184
+ background: "rgba(0,0,0,0.55)",
4185
+ backdropFilter: "blur(0.6vh)",
4186
+ WebkitBackdropFilter: "blur(0.6vh)",
4187
+ border: "0.1vh solid rgba(255,255,255,0.1)",
4188
+ borderRadius: "var(--mantine-radius-sm)",
4189
+ userSelect: "none",
4190
+ minWidth: "16vh"
4191
+ },
4192
+ children: [
4193
+ /* @__PURE__ */ jsx(FlaskConical, { size: 14, color: "rgba(255,255,255,0.7)" }),
4194
+ /* @__PURE__ */ jsx(
4195
+ Text,
4196
+ {
4197
+ size: "xs",
4198
+ ff: "Akrobat Bold",
4199
+ tt: "uppercase",
4200
+ lts: "0.08em",
4201
+ c: "rgba(255,255,255,0.85)",
4202
+ style: { flex: 1 },
4203
+ children: title
4204
+ }
4205
+ ),
4206
+ /* @__PURE__ */ jsx(ActionIcon, { size: "xs", variant: "transparent", c: "rgba(255,255,255,0.6)", children: open ? /* @__PURE__ */ jsx(ChevronUp, { size: 14 }) : /* @__PURE__ */ jsx(ChevronDown, { size: 14 }) })
4207
+ ]
4208
+ }
4209
+ ),
4210
+ open && /* @__PURE__ */ jsx(
4211
+ Stack,
4212
+ {
4213
+ gap: 4,
4214
+ mt: "xxs",
4215
+ p: "xs",
4216
+ style: {
4217
+ background: "rgba(0,0,0,0.55)",
4218
+ backdropFilter: "blur(0.6vh)",
4219
+ WebkitBackdropFilter: "blur(0.6vh)",
4220
+ border: "0.1vh solid rgba(255,255,255,0.1)",
4221
+ borderRadius: "var(--mantine-radius-sm)",
4222
+ minWidth: "16vh",
4223
+ maxHeight: "80vh",
4224
+ overflowY: "auto"
4225
+ },
4226
+ children: items.map((item) => /* @__PURE__ */ jsxs(
4227
+ Flex,
4228
+ {
4229
+ align: "center",
4230
+ justify: "space-between",
4231
+ gap: "xs",
4232
+ px: "xs",
4233
+ py: "xxs",
4234
+ onClick: () => toggle(item),
4235
+ style: {
4236
+ cursor: "pointer",
4237
+ borderRadius: "var(--mantine-radius-xs)",
4238
+ background: item.active ? "rgba(245,158,11,0.15)" : "rgba(255,255,255,0.03)",
4239
+ border: `0.1vh solid ${item.active ? "rgba(245,158,11,0.35)" : "rgba(255,255,255,0.05)"}`,
4240
+ userSelect: "none"
4241
+ },
4242
+ children: [
4243
+ /* @__PURE__ */ jsx(
4244
+ Text,
4245
+ {
4246
+ size: "xs",
4247
+ ff: "Akrobat Bold",
4248
+ c: item.active ? "#f59e0b" : "rgba(255,255,255,0.75)",
4249
+ children: item.label
4250
+ }
4251
+ ),
4252
+ /* @__PURE__ */ jsx(
4253
+ Text,
4254
+ {
4255
+ size: "xxs",
4256
+ ff: "Akrobat Bold",
4257
+ tt: "uppercase",
4258
+ lts: "0.06em",
4259
+ c: item.active ? "#f59e0b" : "rgba(255,255,255,0.35)",
4260
+ children: item.active ? "On" : "Off"
4261
+ }
4262
+ )
4263
+ ]
4264
+ },
4265
+ item.key
4266
+ ))
4267
+ }
4268
+ )
4269
+ ]
4270
+ }
4271
+ );
4272
+ }
4071
4273
 
4072
- export { AdminPageTitle, AsyncSaveButton, BlipColorSelect, BlipIconSelect, BorderedIcon, ConfirmModal, Counter, FiveMKeyBindInput, FloatingParticles, InfoBox, InputContainer, LevelBanner, LevelPanel, Modal, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PromptModal, SegmentedControl, SegmentedProgress, SelectItem, SettingsPanel, Title, useModal, useModalActions, useNavigation, useNavigationStore };
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 };
4073
4275
  //# sourceMappingURL=index.js.map
4074
4276
  //# sourceMappingURL=index.js.map