"use client"; import type { AnyNode, BaseNode, BuildingNode, LevelNode, Zone, } from "@pascal-app/core"; import type { Object3D } from "three"; import { create } from "zustand"; type SelectionPath = { buildingId: BuildingNode["id"] | null; levelId: LevelNode["id"] | null; zoneId: Zone["id"] | null; selectedIds: BaseNode["id"][]; // For items/assets (multi-select) }; type Outliner = { selectedObjects: Object3D[]; hoveredObjects: Object3D[]; }; type ViewerState = { selection: SelectionPath; hoveredId: AnyNode["id"] | Zone["id"] | null; setHoveredId: (id: AnyNode["id"] | Zone["id"] | null) => void; cameraMode: "perspective" | "orthographic"; setCameraMode: (mode: "perspective" | "orthographic") => void; levelMode: "stacked" | "exploded" | "solo" | "manual"; setLevelMode: (mode: "stacked" | "exploded" | "solo" | "manual") => void; // Smart selection update setSelection: (updates: Partial) => void; resetSelection: () => void; outliner: Outliner; // No setter as we will manipulate directly the arrays }; const useViewer = create()((set, get) => ({ selection: { buildingId: null, levelId: null, zoneId: null, selectedIds: [] }, hoveredId: null, setHoveredId: (id) => set({ hoveredId: id }), cameraMode: "perspective", setCameraMode: (mode) => set({ cameraMode: mode }), levelMode: "stacked", setLevelMode: (mode) => set({ levelMode: mode }), setSelection: (updates) => set((state) => { const newSelection = { ...state.selection, ...updates }; // Hierarchy Guard: If we change a high-level parent, reset the children if (updates.buildingId !== undefined) { newSelection.levelId = null; newSelection.zoneId = null; newSelection.selectedIds = []; } else if (updates.levelId !== undefined) { newSelection.zoneId = null; newSelection.selectedIds = []; } else if (updates.zoneId !== undefined) { newSelection.selectedIds = []; } return { selection: newSelection }; }), resetSelection: () => set({ selection: { buildingId: null, levelId: null, zoneId: null, selectedIds: [], }, }), outliner: { selectedObjects: [], hoveredObjects: [] }, })); export default useViewer;