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
|
@@ -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
|
|
3302
|
-
throw new Error("[dirk-cfx-react]
|
|
3303
|
+
function getScriptConfigInstance() {
|
|
3304
|
+
throw new Error("[dirk-cfx-react] createScriptConfig must be called before using ConfigPanel");
|
|
3303
3305
|
}
|
|
3304
|
-
var
|
|
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
|
|
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: "
|
|
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
|
|
3529
|
+
function ConfigHistoryModal({
|
|
3528
3530
|
onClose
|
|
3529
3531
|
}) {
|
|
3530
|
-
const { getHistory } =
|
|
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: ["
|
|
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
|
|
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: "
|
|
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
|
|
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
|
-
|
|
3627
|
+
defaultConfig,
|
|
3626
3628
|
width,
|
|
3627
3629
|
height
|
|
3628
3630
|
}) {
|
|
3629
|
-
const {
|
|
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 [
|
|
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
|
-
|
|
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(
|
|
3656
|
-
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
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
|
|
3662
|
-
confirmLabel: "Reset
|
|
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:
|
|
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
|
-
|
|
3680
|
-
|
|
3694
|
+
const action = pendingAction;
|
|
3695
|
+
setPendingAction(null);
|
|
3696
|
+
if (action === "back") goBack();
|
|
3697
|
+
else onClose();
|
|
3681
3698
|
},
|
|
3682
|
-
onClose: () =>
|
|
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: "
|
|
3710
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3711
|
-
|
|
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
|
|
3869
|
+
function cloneConfig(value) {
|
|
3829
3870
|
return JSON.parse(JSON.stringify(value));
|
|
3830
3871
|
}
|
|
3831
3872
|
function ServerOnlyFetcher() {
|
|
3832
|
-
const {
|
|
3873
|
+
const { fetchConfig } = getScriptConfigInstance();
|
|
3833
3874
|
const { reinitialize } = useFormActions();
|
|
3834
3875
|
react.useEffect(() => {
|
|
3835
3876
|
let cancelled = false;
|
|
3836
|
-
|
|
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
|
|
3888
|
+
function ConfigPanel(props) {
|
|
3848
3889
|
const { open, onClose = defaultOnClose } = props;
|
|
3849
|
-
const { store,
|
|
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:
|
|
3893
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: configPanelQueryClient, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3853
3894
|
FormProvider,
|
|
3854
3895
|
{
|
|
3855
|
-
initialValues:
|
|
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
|
|
3901
|
+
const result = await updateConfig(form.values);
|
|
3861
3902
|
if (result?.success) {
|
|
3862
|
-
form.reinitialize(
|
|
3863
|
-
|
|
3903
|
+
form.reinitialize(cloneConfig(form.values));
|
|
3904
|
+
configPanelQueryClient.invalidateQueries({ queryKey: ["scriptConfigHistory"] });
|
|
3864
3905
|
return;
|
|
3865
3906
|
}
|
|
3866
|
-
form.reinitialize(
|
|
3907
|
+
form.reinitialize(cloneConfig(store.getState()));
|
|
3867
3908
|
if (result?._error) {
|
|
3868
|
-
console.warn(`[
|
|
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
|
-
|
|
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.
|
|
4309
|
+
exports.TestBed = TestBed;
|
|
4114
4310
|
exports.Title = Title;
|
|
4115
4311
|
exports.useModal = useModal;
|
|
4116
4312
|
exports.useModalActions = useModalActions;
|