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.
- package/dist/components/index.cjs +242 -46
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.cts +64 -16
- package/dist/components/index.d.ts +64 -16
- package/dist/components/index.js +243 -48
- package/dist/components/index.js.map +1 -1
- package/dist/hooks/index.cjs +35 -24
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.cts +27 -19
- package/dist/hooks/index.d.ts +27 -19
- package/dist/hooks/index.js +34 -23
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.cjs +277 -72
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +276 -72
- package/dist/index.js.map +1 -1
- package/dist/providers/index.cjs.map +1 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/utils/index.cjs +4 -4
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +4 -4
- package/dist/utils/index.js.map +1 -1
- package/package.json +6 -7
package/dist/components/index.js
CHANGED
|
@@ -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
|
|
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
|
|
@@ -2668,7 +2670,7 @@ function Modal({
|
|
|
2668
2670
|
children: description
|
|
2669
2671
|
}
|
|
2670
2672
|
) }),
|
|
2671
|
-
children
|
|
2673
|
+
/* @__PURE__ */ jsx("div", { style: { flex: 1, minHeight: 0, display: "flex", flexDirection: "column" }, children })
|
|
2672
2674
|
]
|
|
2673
2675
|
}
|
|
2674
2676
|
)
|
|
@@ -3291,10 +3293,10 @@ function useFormActions() {
|
|
|
3291
3293
|
}
|
|
3292
3294
|
return store.getState();
|
|
3293
3295
|
}
|
|
3294
|
-
function
|
|
3295
|
-
throw new Error("[dirk-cfx-react]
|
|
3296
|
+
function getScriptConfigInstance() {
|
|
3297
|
+
throw new Error("[dirk-cfx-react] createScriptConfig must be called before using ConfigPanel");
|
|
3296
3298
|
}
|
|
3297
|
-
var
|
|
3299
|
+
var configPanelQueryClient = new QueryClient({
|
|
3298
3300
|
defaultOptions: { queries: { staleTime: 3e4, gcTime: 5 * 6e4 } }
|
|
3299
3301
|
});
|
|
3300
3302
|
function NavItemButton({
|
|
@@ -3338,7 +3340,7 @@ function NavItemButton({
|
|
|
3338
3340
|
}
|
|
3339
3341
|
);
|
|
3340
3342
|
}
|
|
3341
|
-
function
|
|
3343
|
+
function ConfigJsonModal({
|
|
3342
3344
|
onClose,
|
|
3343
3345
|
schema
|
|
3344
3346
|
}) {
|
|
@@ -3375,7 +3377,7 @@ function SettingsJsonModal({
|
|
|
3375
3377
|
setError(e.message);
|
|
3376
3378
|
}
|
|
3377
3379
|
};
|
|
3378
|
-
return /* @__PURE__ */ jsxs(Modal, { title: "
|
|
3380
|
+
return /* @__PURE__ */ jsxs(Modal, { title: "Config JSON", icon: Code2, iconColor: color, onClose, width: "60vh", maxHeight: "80vh", zIndex: 200, children: [
|
|
3379
3381
|
/* @__PURE__ */ jsxs(Box, { flex: 1, p: "0.8vh", style: { overflowY: "auto" }, children: [
|
|
3380
3382
|
/* @__PURE__ */ jsx(
|
|
3381
3383
|
JsonInput,
|
|
@@ -3517,10 +3519,10 @@ function HistoryTableHeader() {
|
|
|
3517
3519
|
/* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: "Version" })
|
|
3518
3520
|
] });
|
|
3519
3521
|
}
|
|
3520
|
-
function
|
|
3522
|
+
function ConfigHistoryModal({
|
|
3521
3523
|
onClose
|
|
3522
3524
|
}) {
|
|
3523
|
-
const { getHistory } =
|
|
3525
|
+
const { getHistory } = getScriptConfigInstance();
|
|
3524
3526
|
const theme = useMantineTheme();
|
|
3525
3527
|
const color = theme.colors[theme.primaryColor][5];
|
|
3526
3528
|
const [queryInput, setQueryInput] = useState("");
|
|
@@ -3532,7 +3534,7 @@ function SettingsHistoryModal({
|
|
|
3532
3534
|
const [expandedKey, setExpandedKey] = useState(null);
|
|
3533
3535
|
const filters = useMemo(() => ({ query, path, admin }), [query, path, admin]);
|
|
3534
3536
|
const historyQuery = useInfiniteQuery({
|
|
3535
|
-
queryKey: ["
|
|
3537
|
+
queryKey: ["scriptConfigHistory", filters],
|
|
3536
3538
|
initialPageParam: 0,
|
|
3537
3539
|
queryFn: async ({ pageParam }) => {
|
|
3538
3540
|
const response = await getHistory({
|
|
@@ -3543,7 +3545,7 @@ function SettingsHistoryModal({
|
|
|
3543
3545
|
admin: filters.admin || void 0
|
|
3544
3546
|
});
|
|
3545
3547
|
if (!response?.success || !response.data) {
|
|
3546
|
-
throw new Error(response?._error || "Failed to load
|
|
3548
|
+
throw new Error(response?._error || "Failed to load config history");
|
|
3547
3549
|
}
|
|
3548
3550
|
return response.data;
|
|
3549
3551
|
},
|
|
@@ -3557,7 +3559,7 @@ function SettingsHistoryModal({
|
|
|
3557
3559
|
historyQuery.fetchNextPage();
|
|
3558
3560
|
}
|
|
3559
3561
|
};
|
|
3560
|
-
return /* @__PURE__ */ jsxs(Modal, { title: "
|
|
3562
|
+
return /* @__PURE__ */ jsxs(Modal, { title: "Config History", icon: History, iconColor: color, onClose, width: "88vh", maxHeight: "82vh", zIndex: 260, children: [
|
|
3561
3563
|
/* @__PURE__ */ jsxs(Flex, { direction: "column", style: { flex: 1, minHeight: 0 }, children: [
|
|
3562
3564
|
/* @__PURE__ */ jsxs(Flex, { gap: "xs", p: "sm", style: { borderBottom: `0.1vh solid ${alpha(theme.colors.dark[7], 0.8)}` }, children: [
|
|
3563
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 } }),
|
|
@@ -3606,7 +3608,7 @@ function SettingsHistoryModal({
|
|
|
3606
3608
|
) })
|
|
3607
3609
|
] });
|
|
3608
3610
|
}
|
|
3609
|
-
function
|
|
3611
|
+
function ConfigPanelInner({
|
|
3610
3612
|
navItems,
|
|
3611
3613
|
title,
|
|
3612
3614
|
subtitle,
|
|
@@ -3615,28 +3617,37 @@ function SettingsPanelInner({
|
|
|
3615
3617
|
onClose,
|
|
3616
3618
|
schema,
|
|
3617
3619
|
resetConfirmText,
|
|
3618
|
-
|
|
3620
|
+
defaultConfig,
|
|
3619
3621
|
width,
|
|
3620
3622
|
height
|
|
3621
3623
|
}) {
|
|
3622
|
-
const {
|
|
3624
|
+
const { updateConfig, resetConfig, getHistory } = getScriptConfigInstance();
|
|
3623
3625
|
const form = useForm();
|
|
3624
3626
|
const theme = useMantineTheme();
|
|
3625
3627
|
const color = theme.colors[theme.primaryColor][5];
|
|
3626
3628
|
const version = useSettings((s) => s.resourceVersion);
|
|
3627
3629
|
const [activeTab, setActiveTab] = useState(navItems[0]?.id ?? "");
|
|
3630
|
+
const firstMountRef = useRef(true);
|
|
3628
3631
|
const [jsonOpen, setJsonOpen] = useState(false);
|
|
3629
3632
|
const [historyOpen, setHistoryOpen] = useState(false);
|
|
3630
3633
|
const [resetOpen, setResetOpen] = useState(false);
|
|
3631
|
-
const [
|
|
3634
|
+
const [pendingAction, setPendingAction] = useState(null);
|
|
3632
3635
|
const changedCount = form.changedCount ?? 0;
|
|
3633
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
|
+
};
|
|
3634
3645
|
useEffect(() => {
|
|
3635
3646
|
function handleKeyDown(e) {
|
|
3636
3647
|
if (e.key !== "Escape") return;
|
|
3637
3648
|
if (isDirty) {
|
|
3638
3649
|
e.preventDefault();
|
|
3639
|
-
|
|
3650
|
+
setPendingAction("close");
|
|
3640
3651
|
return;
|
|
3641
3652
|
}
|
|
3642
3653
|
onClose();
|
|
@@ -3645,34 +3656,40 @@ function SettingsPanelInner({
|
|
|
3645
3656
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
3646
3657
|
}, [isDirty, onClose]);
|
|
3647
3658
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3648
|
-
/* @__PURE__ */ jsx(AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsx(
|
|
3649
|
-
/* @__PURE__ */ jsx(AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsx(
|
|
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) }) }),
|
|
3650
3661
|
/* @__PURE__ */ jsx(AnimatePresence, { children: resetOpen && /* @__PURE__ */ jsx(
|
|
3651
3662
|
ConfirmModal,
|
|
3652
3663
|
{
|
|
3653
3664
|
title: "Reset to Defaults",
|
|
3654
|
-
description: "This will permanently reset ALL
|
|
3655
|
-
confirmLabel: "Reset
|
|
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",
|
|
3656
3667
|
confirmText: resetConfirmText,
|
|
3657
|
-
onConfirm: () => {
|
|
3658
|
-
updateSettings(defaultSettings).then(() => form.reinitialize(cloneSettings(defaultSettings)));
|
|
3668
|
+
onConfirm: async () => {
|
|
3659
3669
|
setResetOpen(false);
|
|
3670
|
+
const result = await resetConfig();
|
|
3671
|
+
if (result?.success) {
|
|
3672
|
+
const { store } = getScriptConfigInstance();
|
|
3673
|
+
form.reinitialize(cloneConfig(store.getState()));
|
|
3674
|
+
}
|
|
3660
3675
|
},
|
|
3661
3676
|
onClose: () => setResetOpen(false),
|
|
3662
3677
|
zIndex: 300
|
|
3663
3678
|
}
|
|
3664
3679
|
) }),
|
|
3665
|
-
/* @__PURE__ */ jsx(AnimatePresence, { children:
|
|
3680
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: pendingAction !== null && /* @__PURE__ */ jsx(
|
|
3666
3681
|
ConfirmModal,
|
|
3667
3682
|
{
|
|
3668
3683
|
title: "Discard Unsaved Changes?",
|
|
3669
|
-
description: "You have unsaved changes. Closing now will discard them.",
|
|
3670
|
-
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",
|
|
3671
3686
|
onConfirm: () => {
|
|
3672
|
-
|
|
3673
|
-
|
|
3687
|
+
const action = pendingAction;
|
|
3688
|
+
setPendingAction(null);
|
|
3689
|
+
if (action === "back") goBack();
|
|
3690
|
+
else onClose();
|
|
3674
3691
|
},
|
|
3675
|
-
onClose: () =>
|
|
3692
|
+
onClose: () => setPendingAction(null),
|
|
3676
3693
|
zIndex: 300
|
|
3677
3694
|
}
|
|
3678
3695
|
) }),
|
|
@@ -3699,9 +3716,33 @@ function SettingsPanelInner({
|
|
|
3699
3716
|
exit: { scale: 0.3, opacity: 0, transform: "translate(-50%, -50%)" },
|
|
3700
3717
|
children: [
|
|
3701
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: [
|
|
3702
|
-
/* @__PURE__ */ jsxs(Flex, { align: "
|
|
3703
|
-
/* @__PURE__ */ jsx(
|
|
3704
|
-
|
|
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
|
+
] })
|
|
3705
3746
|
] }),
|
|
3706
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: [
|
|
3707
3748
|
/* @__PURE__ */ jsx(
|
|
@@ -3804,7 +3845,7 @@ function SettingsPanelInner({
|
|
|
3804
3845
|
/* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
|
|
3805
3846
|
motion.div,
|
|
3806
3847
|
{
|
|
3807
|
-
initial: { opacity: 0, y: 4 },
|
|
3848
|
+
initial: firstMountRef.current ? (firstMountRef.current = false, false) : { opacity: 0, y: 4 },
|
|
3808
3849
|
animate: { opacity: 1, y: 0 },
|
|
3809
3850
|
exit: { opacity: 0, y: -4 },
|
|
3810
3851
|
transition: { duration: 0.15 },
|
|
@@ -3818,15 +3859,15 @@ function SettingsPanelInner({
|
|
|
3818
3859
|
)
|
|
3819
3860
|
] });
|
|
3820
3861
|
}
|
|
3821
|
-
function
|
|
3862
|
+
function cloneConfig(value) {
|
|
3822
3863
|
return JSON.parse(JSON.stringify(value));
|
|
3823
3864
|
}
|
|
3824
3865
|
function ServerOnlyFetcher() {
|
|
3825
|
-
const {
|
|
3866
|
+
const { fetchConfig } = getScriptConfigInstance();
|
|
3826
3867
|
const { reinitialize } = useFormActions();
|
|
3827
3868
|
useEffect(() => {
|
|
3828
3869
|
let cancelled = false;
|
|
3829
|
-
|
|
3870
|
+
fetchConfig().then((full) => {
|
|
3830
3871
|
if (!cancelled && full) reinitialize(full);
|
|
3831
3872
|
}).catch(() => {
|
|
3832
3873
|
});
|
|
@@ -3837,28 +3878,28 @@ function ServerOnlyFetcher() {
|
|
|
3837
3878
|
return null;
|
|
3838
3879
|
}
|
|
3839
3880
|
var defaultOnClose = () => fetchNui("CLOSE_ADMIN_SECTION");
|
|
3840
|
-
function
|
|
3881
|
+
function ConfigPanel(props) {
|
|
3841
3882
|
const { open, onClose = defaultOnClose } = props;
|
|
3842
|
-
const { store,
|
|
3883
|
+
const { store, updateConfig } = getScriptConfigInstance();
|
|
3843
3884
|
const [isSaving, setIsSaving] = useState(false);
|
|
3844
3885
|
if (!open) return null;
|
|
3845
|
-
return /* @__PURE__ */ jsx(QueryClientProvider, { client:
|
|
3886
|
+
return /* @__PURE__ */ jsx(QueryClientProvider, { client: configPanelQueryClient, children: /* @__PURE__ */ jsxs(
|
|
3846
3887
|
FormProvider,
|
|
3847
3888
|
{
|
|
3848
|
-
initialValues:
|
|
3889
|
+
initialValues: cloneConfig(store.getState()),
|
|
3849
3890
|
onSubmit: async (form) => {
|
|
3850
3891
|
if (isSaving) return;
|
|
3851
3892
|
setIsSaving(true);
|
|
3852
3893
|
try {
|
|
3853
|
-
const result = await
|
|
3894
|
+
const result = await updateConfig(form.values);
|
|
3854
3895
|
if (result?.success) {
|
|
3855
|
-
form.reinitialize(
|
|
3856
|
-
|
|
3896
|
+
form.reinitialize(cloneConfig(form.values));
|
|
3897
|
+
configPanelQueryClient.invalidateQueries({ queryKey: ["scriptConfigHistory"] });
|
|
3857
3898
|
return;
|
|
3858
3899
|
}
|
|
3859
|
-
form.reinitialize(
|
|
3900
|
+
form.reinitialize(cloneConfig(store.getState()));
|
|
3860
3901
|
if (result?._error) {
|
|
3861
|
-
console.warn(`[
|
|
3902
|
+
console.warn(`[ConfigPanel] config save failed: ${result._error}`);
|
|
3862
3903
|
}
|
|
3863
3904
|
} finally {
|
|
3864
3905
|
setIsSaving(false);
|
|
@@ -3867,7 +3908,7 @@ function SettingsPanel(props) {
|
|
|
3867
3908
|
children: [
|
|
3868
3909
|
/* @__PURE__ */ jsx(ServerOnlyFetcher, {}),
|
|
3869
3910
|
/* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(
|
|
3870
|
-
|
|
3911
|
+
ConfigPanelInner,
|
|
3871
3912
|
{
|
|
3872
3913
|
...props,
|
|
3873
3914
|
onClose,
|
|
@@ -4075,7 +4116,161 @@ function AdminPageTitle(props) {
|
|
|
4075
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) })
|
|
4076
4117
|
] });
|
|
4077
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
|
+
}
|
|
4078
4273
|
|
|
4079
|
-
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,
|
|
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 };
|
|
4080
4275
|
//# sourceMappingURL=index.js.map
|
|
4081
4276
|
//# sourceMappingURL=index.js.map
|