dirk-cfx-react 1.1.58 → 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.
@@ -1299,6 +1299,7 @@ var localeStore = zustand.create((set, get) => {
1299
1299
  var locale = localeStore.getState().locale;
1300
1300
  registerInitialFetch("GET_LOCALES", void 0).then((data) => {
1301
1301
  localeStore.setState({ locales: data });
1302
+ }).catch(() => {
1302
1303
  });
1303
1304
  var useItems = zustand.create(() => ({}));
1304
1305
  var useItemsList = (excludeItemNames = []) => {
@@ -1312,6 +1313,7 @@ registerInitialFetch("FETCH_ALL_ITEMS", null, {
1312
1313
  }).then((fetchedItems) => {
1313
1314
  if (!fetchedItems) return;
1314
1315
  useItems.setState(fetchedItems);
1316
+ }).catch(() => {
1315
1317
  });
1316
1318
 
1317
1319
  // src/utils/inputMapper.ts
@@ -2675,7 +2677,7 @@ function Modal({
2675
2677
  children: description
2676
2678
  }
2677
2679
  ) }),
2678
- children
2680
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, minHeight: 0, display: "flex", flexDirection: "column" }, children })
2679
2681
  ]
2680
2682
  }
2681
2683
  )
@@ -3298,10 +3300,10 @@ function useFormActions() {
3298
3300
  }
3299
3301
  return store.getState();
3300
3302
  }
3301
- function getScriptSettingsInstance() {
3302
- throw new Error("[dirk-cfx-react] createScriptSettings must be called before using SettingsPanel");
3303
+ function getScriptConfigInstance() {
3304
+ throw new Error("[dirk-cfx-react] createScriptConfig must be called before using ConfigPanel");
3303
3305
  }
3304
- var settingsPanelQueryClient = new reactQuery.QueryClient({
3306
+ var configPanelQueryClient = new reactQuery.QueryClient({
3305
3307
  defaultOptions: { queries: { staleTime: 3e4, gcTime: 5 * 6e4 } }
3306
3308
  });
3307
3309
  function NavItemButton({
@@ -3345,7 +3347,7 @@ function NavItemButton({
3345
3347
  }
3346
3348
  );
3347
3349
  }
3348
- function SettingsJsonModal({
3350
+ function ConfigJsonModal({
3349
3351
  onClose,
3350
3352
  schema
3351
3353
  }) {
@@ -3382,7 +3384,7 @@ function SettingsJsonModal({
3382
3384
  setError(e.message);
3383
3385
  }
3384
3386
  };
3385
- return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "Settings JSON", icon: lucideReact.Code2, iconColor: color, onClose, width: "60vh", maxHeight: "80vh", zIndex: 200, children: [
3387
+ return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "Config JSON", icon: lucideReact.Code2, iconColor: color, onClose, width: "60vh", maxHeight: "80vh", zIndex: 200, children: [
3386
3388
  /* @__PURE__ */ jsxRuntime.jsxs(core.Box, { flex: 1, p: "0.8vh", style: { overflowY: "auto" }, children: [
3387
3389
  /* @__PURE__ */ jsxRuntime.jsx(
3388
3390
  core.JsonInput,
@@ -3524,10 +3526,10 @@ function HistoryTableHeader() {
3524
3526
  /* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: "Version" })
3525
3527
  ] });
3526
3528
  }
3527
- function SettingsHistoryModal({
3529
+ function ConfigHistoryModal({
3528
3530
  onClose
3529
3531
  }) {
3530
- const { getHistory } = getScriptSettingsInstance();
3532
+ const { getHistory } = getScriptConfigInstance();
3531
3533
  const theme = core.useMantineTheme();
3532
3534
  const color = theme.colors[theme.primaryColor][5];
3533
3535
  const [queryInput, setQueryInput] = react.useState("");
@@ -3539,7 +3541,7 @@ function SettingsHistoryModal({
3539
3541
  const [expandedKey, setExpandedKey] = react.useState(null);
3540
3542
  const filters = react.useMemo(() => ({ query, path, admin }), [query, path, admin]);
3541
3543
  const historyQuery = reactQuery.useInfiniteQuery({
3542
- queryKey: ["scriptSettingsHistory", filters],
3544
+ queryKey: ["scriptConfigHistory", filters],
3543
3545
  initialPageParam: 0,
3544
3546
  queryFn: async ({ pageParam }) => {
3545
3547
  const response = await getHistory({
@@ -3550,7 +3552,7 @@ function SettingsHistoryModal({
3550
3552
  admin: filters.admin || void 0
3551
3553
  });
3552
3554
  if (!response?.success || !response.data) {
3553
- throw new Error(response?._error || "Failed to load settings history");
3555
+ throw new Error(response?._error || "Failed to load config history");
3554
3556
  }
3555
3557
  return response.data;
3556
3558
  },
@@ -3564,7 +3566,7 @@ function SettingsHistoryModal({
3564
3566
  historyQuery.fetchNextPage();
3565
3567
  }
3566
3568
  };
3567
- return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "Settings History", icon: lucideReact.History, iconColor: color, onClose, width: "88vh", maxHeight: "82vh", zIndex: 260, children: [
3569
+ return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { title: "Config History", icon: lucideReact.History, iconColor: color, onClose, width: "88vh", maxHeight: "82vh", zIndex: 260, children: [
3568
3570
  /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { flex: 1, minHeight: 0 }, children: [
3569
3571
  /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { gap: "xs", p: "sm", style: { borderBottom: `0.1vh solid ${core.alpha(theme.colors.dark[7], 0.8)}` }, children: [
3570
3572
  /* @__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 } }),
@@ -3613,7 +3615,7 @@ function SettingsHistoryModal({
3613
3615
  ) })
3614
3616
  ] });
3615
3617
  }
3616
- function SettingsPanelInner({
3618
+ function ConfigPanelInner({
3617
3619
  navItems,
3618
3620
  title,
3619
3621
  subtitle,
@@ -3622,28 +3624,37 @@ function SettingsPanelInner({
3622
3624
  onClose,
3623
3625
  schema,
3624
3626
  resetConfirmText,
3625
- defaultSettings,
3627
+ defaultConfig,
3626
3628
  width,
3627
3629
  height
3628
3630
  }) {
3629
- const { updateSettings, getHistory } = getScriptSettingsInstance();
3631
+ const { updateConfig, resetConfig, getHistory } = getScriptConfigInstance();
3630
3632
  const form = useForm();
3631
3633
  const theme = core.useMantineTheme();
3632
3634
  const color = theme.colors[theme.primaryColor][5];
3633
3635
  const version = useSettings((s) => s.resourceVersion);
3634
3636
  const [activeTab, setActiveTab] = react.useState(navItems[0]?.id ?? "");
3637
+ const firstMountRef = react.useRef(true);
3635
3638
  const [jsonOpen, setJsonOpen] = react.useState(false);
3636
3639
  const [historyOpen, setHistoryOpen] = react.useState(false);
3637
3640
  const [resetOpen, setResetOpen] = react.useState(false);
3638
- const [closeConfirmOpen, setCloseConfirmOpen] = react.useState(false);
3641
+ const [pendingAction, setPendingAction] = react.useState(null);
3639
3642
  const changedCount = form.changedCount ?? 0;
3640
3643
  const isDirty = changedCount > 0;
3644
+ const goBack = () => fetchNui("CONFIG_PANEL_BACK");
3645
+ const handleBack = () => {
3646
+ if (isDirty) {
3647
+ setPendingAction("back");
3648
+ return;
3649
+ }
3650
+ goBack();
3651
+ };
3641
3652
  react.useEffect(() => {
3642
3653
  function handleKeyDown(e) {
3643
3654
  if (e.key !== "Escape") return;
3644
3655
  if (isDirty) {
3645
3656
  e.preventDefault();
3646
- setCloseConfirmOpen(true);
3657
+ setPendingAction("close");
3647
3658
  return;
3648
3659
  }
3649
3660
  onClose();
@@ -3652,34 +3663,40 @@ function SettingsPanelInner({
3652
3663
  return () => window.removeEventListener("keydown", handleKeyDown);
3653
3664
  }, [isDirty, onClose]);
3654
3665
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3655
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsxRuntime.jsx(SettingsJsonModal, { onClose: () => setJsonOpen(false), schema }) }),
3656
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsxRuntime.jsx(SettingsHistoryModal, { onClose: () => setHistoryOpen(false) }) }),
3666
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsxRuntime.jsx(ConfigJsonModal, { onClose: () => setJsonOpen(false), schema }) }),
3667
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsxRuntime.jsx(ConfigHistoryModal, { onClose: () => setHistoryOpen(false) }) }),
3657
3668
  /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: resetOpen && /* @__PURE__ */ jsxRuntime.jsx(
3658
3669
  ConfirmModal,
3659
3670
  {
3660
3671
  title: "Reset to Defaults",
3661
- description: "This will permanently reset ALL settings back to their defaults. Every setting you have configured will be overwritten. This cannot be undone.",
3662
- confirmLabel: "Reset Settings",
3672
+ description: "This will permanently reset ALL config back to the defaults. Every value you have configured will be overwritten. This cannot be undone.",
3673
+ confirmLabel: "Reset Config",
3663
3674
  confirmText: resetConfirmText,
3664
- onConfirm: () => {
3665
- updateSettings(defaultSettings).then(() => form.reinitialize(cloneSettings(defaultSettings)));
3675
+ onConfirm: async () => {
3666
3676
  setResetOpen(false);
3677
+ const result = await resetConfig();
3678
+ if (result?.success) {
3679
+ const { store } = getScriptConfigInstance();
3680
+ form.reinitialize(cloneConfig(store.getState()));
3681
+ }
3667
3682
  },
3668
3683
  onClose: () => setResetOpen(false),
3669
3684
  zIndex: 300
3670
3685
  }
3671
3686
  ) }),
3672
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: closeConfirmOpen && /* @__PURE__ */ jsxRuntime.jsx(
3687
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: pendingAction !== null && /* @__PURE__ */ jsxRuntime.jsx(
3673
3688
  ConfirmModal,
3674
3689
  {
3675
3690
  title: "Discard Unsaved Changes?",
3676
- description: "You have unsaved changes. Closing now will discard them.",
3677
- confirmLabel: "Close Without Saving",
3691
+ description: pendingAction === "back" ? "You have unsaved changes. Going back now will discard them." : "You have unsaved changes. Closing now will discard them.",
3692
+ confirmLabel: pendingAction === "back" ? "Go Back Without Saving" : "Close Without Saving",
3678
3693
  onConfirm: () => {
3679
- setCloseConfirmOpen(false);
3680
- onClose();
3694
+ const action = pendingAction;
3695
+ setPendingAction(null);
3696
+ if (action === "back") goBack();
3697
+ else onClose();
3681
3698
  },
3682
- onClose: () => setCloseConfirmOpen(false),
3699
+ onClose: () => setPendingAction(null),
3683
3700
  zIndex: 300
3684
3701
  }
3685
3702
  ) }),
@@ -3706,9 +3723,33 @@ function SettingsPanelInner({
3706
3723
  exit: { scale: 0.3, opacity: 0, transform: "translate(-50%, -50%)" },
3707
3724
  children: [
3708
3725
  /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { width: "18vh", flexShrink: 0, borderRight: `0.1vh solid ${core.alpha(theme.colors.dark[6], 0.8)}`, background: core.alpha(theme.colors.dark[8], 0.6), overflow: "hidden" }, children: [
3709
- /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "baseline", gap: "0.3vh", px: "sm", py: "sm", style: { borderBottom: `0.1vh solid ${core.alpha(theme.colors.dark[6], 0.5)}`, flexShrink: 0 }, children: [
3710
- /* @__PURE__ */ jsxRuntime.jsx(core.Text, { size: "lg", ff: "Akrobat Bold", tt: "uppercase", children: title }),
3711
- subtitle && /* @__PURE__ */ jsxRuntime.jsx(core.Text, { tt: "uppercase", fw: 600, c: color, children: subtitle })
3726
+ /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { align: "center", gap: "0.6vh", px: "sm", py: "sm", style: { borderBottom: `0.1vh solid ${core.alpha(theme.colors.dark[6], 0.5)}`, flexShrink: 0 }, children: [
3727
+ /* @__PURE__ */ jsxRuntime.jsx(
3728
+ framerMotion.motion.button,
3729
+ {
3730
+ title: "Back to script list",
3731
+ onClick: handleBack,
3732
+ whileHover: { background: core.alpha(color, 0.16), borderColor: core.alpha(color, 0.45) },
3733
+ whileTap: { scale: 0.95 },
3734
+ style: {
3735
+ aspectRatio: "1 / 1",
3736
+ height: "2.4vh",
3737
+ background: core.alpha(color, 0.08),
3738
+ border: `0.1vh solid ${core.alpha(color, 0.3)}`,
3739
+ borderRadius: theme.radius.xs,
3740
+ cursor: "pointer",
3741
+ display: "flex",
3742
+ alignItems: "center",
3743
+ justifyContent: "center",
3744
+ flexShrink: 0
3745
+ },
3746
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { size: "1.4vh", color })
3747
+ }
3748
+ ),
3749
+ /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { direction: "column", style: { minWidth: 0, lineHeight: 1 }, children: [
3750
+ /* @__PURE__ */ jsxRuntime.jsx(core.Text, { size: "lg", ff: "Akrobat Bold", tt: "uppercase", lts: "0.04em", truncate: true, children: title }),
3751
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx(core.Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.08em", c: color, truncate: true, children: subtitle })
3752
+ ] })
3712
3753
  ] }),
3713
3754
  /* @__PURE__ */ jsxRuntime.jsxs(core.Flex, { gap: "xxs", px: "xs", py: "xs", style: { borderBottom: `0.1vh solid ${core.alpha(theme.colors.dark[6], 0.4)}`, flexShrink: 0 }, children: [
3714
3755
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -3811,7 +3852,7 @@ function SettingsPanelInner({
3811
3852
  /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsxRuntime.jsx(
3812
3853
  framerMotion.motion.div,
3813
3854
  {
3814
- initial: { opacity: 0, y: 4 },
3855
+ initial: firstMountRef.current ? (firstMountRef.current = false, false) : { opacity: 0, y: 4 },
3815
3856
  animate: { opacity: 1, y: 0 },
3816
3857
  exit: { opacity: 0, y: -4 },
3817
3858
  transition: { duration: 0.15 },
@@ -3825,15 +3866,15 @@ function SettingsPanelInner({
3825
3866
  )
3826
3867
  ] });
3827
3868
  }
3828
- function cloneSettings(value) {
3869
+ function cloneConfig(value) {
3829
3870
  return JSON.parse(JSON.stringify(value));
3830
3871
  }
3831
3872
  function ServerOnlyFetcher() {
3832
- const { fetchSettings } = getScriptSettingsInstance();
3873
+ const { fetchConfig } = getScriptConfigInstance();
3833
3874
  const { reinitialize } = useFormActions();
3834
3875
  react.useEffect(() => {
3835
3876
  let cancelled = false;
3836
- fetchSettings().then((full) => {
3877
+ fetchConfig().then((full) => {
3837
3878
  if (!cancelled && full) reinitialize(full);
3838
3879
  }).catch(() => {
3839
3880
  });
@@ -3844,28 +3885,28 @@ function ServerOnlyFetcher() {
3844
3885
  return null;
3845
3886
  }
3846
3887
  var defaultOnClose = () => fetchNui("CLOSE_ADMIN_SECTION");
3847
- function SettingsPanel(props) {
3888
+ function ConfigPanel(props) {
3848
3889
  const { open, onClose = defaultOnClose } = props;
3849
- const { store, updateSettings, fetchSettings } = getScriptSettingsInstance();
3890
+ const { store, updateConfig } = getScriptConfigInstance();
3850
3891
  const [isSaving, setIsSaving] = react.useState(false);
3851
3892
  if (!open) return null;
3852
- return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: settingsPanelQueryClient, children: /* @__PURE__ */ jsxRuntime.jsxs(
3893
+ return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: configPanelQueryClient, children: /* @__PURE__ */ jsxRuntime.jsxs(
3853
3894
  FormProvider,
3854
3895
  {
3855
- initialValues: cloneSettings(store.getState()),
3896
+ initialValues: cloneConfig(store.getState()),
3856
3897
  onSubmit: async (form) => {
3857
3898
  if (isSaving) return;
3858
3899
  setIsSaving(true);
3859
3900
  try {
3860
- const result = await updateSettings(form.values);
3901
+ const result = await updateConfig(form.values);
3861
3902
  if (result?.success) {
3862
- form.reinitialize(cloneSettings(form.values));
3863
- settingsPanelQueryClient.invalidateQueries({ queryKey: ["scriptSettingsHistory"] });
3903
+ form.reinitialize(cloneConfig(form.values));
3904
+ configPanelQueryClient.invalidateQueries({ queryKey: ["scriptConfigHistory"] });
3864
3905
  return;
3865
3906
  }
3866
- form.reinitialize(cloneSettings(store.getState()));
3907
+ form.reinitialize(cloneConfig(store.getState()));
3867
3908
  if (result?._error) {
3868
- console.warn(`[SettingsPanel] settings save failed: ${result._error}`);
3909
+ console.warn(`[ConfigPanel] config save failed: ${result._error}`);
3869
3910
  }
3870
3911
  } finally {
3871
3912
  setIsSaving(false);
@@ -3874,7 +3915,7 @@ function SettingsPanel(props) {
3874
3915
  children: [
3875
3916
  /* @__PURE__ */ jsxRuntime.jsx(ServerOnlyFetcher, {}),
3876
3917
  /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: open && /* @__PURE__ */ jsxRuntime.jsx(
3877
- SettingsPanelInner,
3918
+ ConfigPanelInner,
3878
3919
  {
3879
3920
  ...props,
3880
3921
  onClose,
@@ -4082,12 +4123,167 @@ function AdminPageTitle(props) {
4082
4123
  /* @__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) })
4083
4124
  ] });
4084
4125
  }
4126
+ var loadPersistedState = (storageKey) => {
4127
+ try {
4128
+ const raw = localStorage.getItem(storageKey);
4129
+ return raw ? JSON.parse(raw) : {};
4130
+ } catch {
4131
+ return {};
4132
+ }
4133
+ };
4134
+ var savePersistedState = (storageKey, state) => {
4135
+ try {
4136
+ localStorage.setItem(storageKey, JSON.stringify(state));
4137
+ } catch {
4138
+ }
4139
+ };
4140
+ function TestBed({
4141
+ items,
4142
+ storageKey = "testbed:open-state",
4143
+ disablePersistence = false,
4144
+ title = "TestBed"
4145
+ }) {
4146
+ const [open, setOpen] = react.useState(false);
4147
+ const itemsRef = react.useRef(items);
4148
+ itemsRef.current = items;
4149
+ react.useEffect(() => {
4150
+ if (!isEnvBrowser() || disablePersistence) return;
4151
+ const persisted = loadPersistedState(storageKey);
4152
+ itemsRef.current.forEach((item) => {
4153
+ const persistedValue = persisted[item.key];
4154
+ if (typeof persistedValue === "boolean" && persistedValue !== item.active) {
4155
+ item.onToggle(persistedValue);
4156
+ }
4157
+ });
4158
+ }, []);
4159
+ if (!isEnvBrowser()) return null;
4160
+ const toggle = (item) => {
4161
+ const next = !item.active;
4162
+ item.onToggle(next);
4163
+ if (!disablePersistence) {
4164
+ const persisted = loadPersistedState(storageKey);
4165
+ persisted[item.key] = next;
4166
+ savePersistedState(storageKey, persisted);
4167
+ }
4168
+ };
4169
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4170
+ "div",
4171
+ {
4172
+ style: {
4173
+ position: "fixed",
4174
+ top: "1vh",
4175
+ left: "1vh",
4176
+ zIndex: 2147483647,
4177
+ pointerEvents: "auto",
4178
+ fontSize: "1.4vh"
4179
+ },
4180
+ children: [
4181
+ /* @__PURE__ */ jsxRuntime.jsxs(
4182
+ core.Flex,
4183
+ {
4184
+ align: "center",
4185
+ gap: "xs",
4186
+ px: "sm",
4187
+ py: "xs",
4188
+ onClick: () => setOpen((v) => !v),
4189
+ style: {
4190
+ cursor: "pointer",
4191
+ background: "rgba(0,0,0,0.55)",
4192
+ backdropFilter: "blur(0.6vh)",
4193
+ WebkitBackdropFilter: "blur(0.6vh)",
4194
+ border: "0.1vh solid rgba(255,255,255,0.1)",
4195
+ borderRadius: "var(--mantine-radius-sm)",
4196
+ userSelect: "none",
4197
+ minWidth: "16vh"
4198
+ },
4199
+ children: [
4200
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FlaskConical, { size: 14, color: "rgba(255,255,255,0.7)" }),
4201
+ /* @__PURE__ */ jsxRuntime.jsx(
4202
+ core.Text,
4203
+ {
4204
+ size: "xs",
4205
+ ff: "Akrobat Bold",
4206
+ tt: "uppercase",
4207
+ lts: "0.08em",
4208
+ c: "rgba(255,255,255,0.85)",
4209
+ style: { flex: 1 },
4210
+ children: title
4211
+ }
4212
+ ),
4213
+ /* @__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 }) })
4214
+ ]
4215
+ }
4216
+ ),
4217
+ open && /* @__PURE__ */ jsxRuntime.jsx(
4218
+ core.Stack,
4219
+ {
4220
+ gap: 4,
4221
+ mt: "xxs",
4222
+ p: "xs",
4223
+ style: {
4224
+ background: "rgba(0,0,0,0.55)",
4225
+ backdropFilter: "blur(0.6vh)",
4226
+ WebkitBackdropFilter: "blur(0.6vh)",
4227
+ border: "0.1vh solid rgba(255,255,255,0.1)",
4228
+ borderRadius: "var(--mantine-radius-sm)",
4229
+ minWidth: "16vh",
4230
+ maxHeight: "80vh",
4231
+ overflowY: "auto"
4232
+ },
4233
+ children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
4234
+ core.Flex,
4235
+ {
4236
+ align: "center",
4237
+ justify: "space-between",
4238
+ gap: "xs",
4239
+ px: "xs",
4240
+ py: "xxs",
4241
+ onClick: () => toggle(item),
4242
+ style: {
4243
+ cursor: "pointer",
4244
+ borderRadius: "var(--mantine-radius-xs)",
4245
+ background: item.active ? "rgba(245,158,11,0.15)" : "rgba(255,255,255,0.03)",
4246
+ border: `0.1vh solid ${item.active ? "rgba(245,158,11,0.35)" : "rgba(255,255,255,0.05)"}`,
4247
+ userSelect: "none"
4248
+ },
4249
+ children: [
4250
+ /* @__PURE__ */ jsxRuntime.jsx(
4251
+ core.Text,
4252
+ {
4253
+ size: "xs",
4254
+ ff: "Akrobat Bold",
4255
+ c: item.active ? "#f59e0b" : "rgba(255,255,255,0.75)",
4256
+ children: item.label
4257
+ }
4258
+ ),
4259
+ /* @__PURE__ */ jsxRuntime.jsx(
4260
+ core.Text,
4261
+ {
4262
+ size: "xxs",
4263
+ ff: "Akrobat Bold",
4264
+ tt: "uppercase",
4265
+ lts: "0.06em",
4266
+ c: item.active ? "#f59e0b" : "rgba(255,255,255,0.35)",
4267
+ children: item.active ? "On" : "Off"
4268
+ }
4269
+ )
4270
+ ]
4271
+ },
4272
+ item.key
4273
+ ))
4274
+ }
4275
+ )
4276
+ ]
4277
+ }
4278
+ );
4279
+ }
4085
4280
 
4086
4281
  exports.AdminPageTitle = AdminPageTitle;
4087
4282
  exports.AsyncSaveButton = AsyncSaveButton;
4088
4283
  exports.BlipColorSelect = BlipColorSelect;
4089
4284
  exports.BlipIconSelect = BlipIconSelect;
4090
4285
  exports.BorderedIcon = BorderedIcon;
4286
+ exports.ConfigPanel = ConfigPanel;
4091
4287
  exports.ConfirmModal = ConfirmModal;
4092
4288
  exports.Counter = Counter;
4093
4289
  exports.FiveMKeyBindInput = FiveMKeyBindInput;
@@ -4110,7 +4306,7 @@ exports.PromptModal = PromptModal;
4110
4306
  exports.SegmentedControl = SegmentedControl;
4111
4307
  exports.SegmentedProgress = SegmentedProgress;
4112
4308
  exports.SelectItem = SelectItem;
4113
- exports.SettingsPanel = SettingsPanel;
4309
+ exports.TestBed = TestBed;
4114
4310
  exports.Title = Title;
4115
4311
  exports.useModal = useModal;
4116
4312
  exports.useModalActions = useModalActions;