108 lines
2.9 KiB
TypeScript
108 lines
2.9 KiB
TypeScript
import type { CreatureId } from "@initiative/domain";
|
|
import { useCallback, useEffect, useState } from "react";
|
|
|
|
type PanelView =
|
|
| { mode: "closed" }
|
|
| { mode: "creature"; creatureId: CreatureId }
|
|
| { mode: "bulk-import" }
|
|
| { mode: "source-manager" };
|
|
|
|
interface SidePanelState {
|
|
panelView: PanelView;
|
|
selectedCreatureId: CreatureId | null;
|
|
bulkImportMode: boolean;
|
|
sourceManagerMode: boolean;
|
|
isRightPanelCollapsed: boolean;
|
|
pinnedCreatureId: CreatureId | null;
|
|
isWideDesktop: boolean;
|
|
}
|
|
|
|
interface SidePanelActions {
|
|
showCreature: (creatureId: CreatureId) => void;
|
|
updateCreature: (creatureId: CreatureId) => void;
|
|
showBulkImport: () => void;
|
|
showSourceManager: () => void;
|
|
dismissPanel: () => void;
|
|
toggleCollapse: () => void;
|
|
togglePin: () => void;
|
|
unpin: () => void;
|
|
}
|
|
|
|
export function useSidePanelState(): SidePanelState & SidePanelActions {
|
|
const [panelView, setPanelView] = useState<PanelView>({ mode: "closed" });
|
|
const [isRightPanelCollapsed, setIsRightPanelCollapsed] = useState(false);
|
|
const [pinnedCreatureId, setPinnedCreatureId] = useState<CreatureId | null>(
|
|
null,
|
|
);
|
|
const [isWideDesktop, setIsWideDesktop] = useState(
|
|
() => globalThis.matchMedia("(min-width: 1280px)").matches,
|
|
);
|
|
|
|
useEffect(() => {
|
|
const mq = globalThis.matchMedia("(min-width: 1280px)");
|
|
const handler = (e: MediaQueryListEvent) => setIsWideDesktop(e.matches);
|
|
mq.addEventListener("change", handler);
|
|
return () => mq.removeEventListener("change", handler);
|
|
}, []);
|
|
|
|
const selectedCreatureId =
|
|
panelView.mode === "creature" ? panelView.creatureId : null;
|
|
|
|
const showCreature = useCallback((creatureId: CreatureId) => {
|
|
setPanelView({ mode: "creature", creatureId });
|
|
setIsRightPanelCollapsed(false);
|
|
}, []);
|
|
|
|
const updateCreature = useCallback((creatureId: CreatureId) => {
|
|
setPanelView({ mode: "creature", creatureId });
|
|
}, []);
|
|
|
|
const showBulkImport = useCallback(() => {
|
|
setPanelView({ mode: "bulk-import" });
|
|
setIsRightPanelCollapsed(false);
|
|
}, []);
|
|
|
|
const showSourceManager = useCallback(() => {
|
|
setPanelView({ mode: "source-manager" });
|
|
setIsRightPanelCollapsed(false);
|
|
}, []);
|
|
|
|
const dismissPanel = useCallback(() => {
|
|
setPanelView({ mode: "closed" });
|
|
}, []);
|
|
|
|
const toggleCollapse = useCallback(() => {
|
|
setIsRightPanelCollapsed((f) => !f);
|
|
}, []);
|
|
|
|
const togglePin = useCallback(() => {
|
|
if (selectedCreatureId) {
|
|
setPinnedCreatureId((prev) =>
|
|
prev === selectedCreatureId ? null : selectedCreatureId,
|
|
);
|
|
}
|
|
}, [selectedCreatureId]);
|
|
|
|
const unpin = useCallback(() => {
|
|
setPinnedCreatureId(null);
|
|
}, []);
|
|
|
|
return {
|
|
panelView,
|
|
selectedCreatureId,
|
|
bulkImportMode: panelView.mode === "bulk-import",
|
|
sourceManagerMode: panelView.mode === "source-manager",
|
|
isRightPanelCollapsed,
|
|
pinnedCreatureId,
|
|
isWideDesktop,
|
|
showCreature,
|
|
updateCreature,
|
|
showBulkImport,
|
|
showSourceManager,
|
|
dismissPanel,
|
|
toggleCollapse,
|
|
togglePin,
|
|
unpin,
|
|
};
|
|
}
|