import type L from 'leaflet' import { HnHMinZoom, HnHMaxZoom, TileSize } from '~/lib/LeafletCustomTypes' export interface MapLogicState { hideMarkers: Ref panelCollapsed: Ref trackingCharacterId: Ref selectedMapId: Ref overlayMapId: Ref selectedMarkerId: Ref selectedPlayerId: Ref displayCoords: Ref<{ x: number; y: number; z: number } | null> mapid: Ref } export interface ContextMenuTileData { coords: { x: number; y: number } } export interface ContextMenuMarkerData { id: number name: string } export interface ContextMenuState { tile: { show: boolean x: number y: number data: ContextMenuTileData | null } marker: { show: boolean x: number y: number data: ContextMenuMarkerData | null } } export interface CoordSetState { from: { x: number; y: number } to: { x: number; y: number } } /** * Composable for map logic: zoom, display options, overlays, navigation, context menus. * Map instance is passed to functions that need it (set by MapView after init). */ export function useMapLogic() { const hideMarkers = ref(false) const panelCollapsed = ref(false) const trackingCharacterId = ref(-1) const selectedMapId = ref(null) const overlayMapId = ref(-1) const selectedMarkerId = ref(null) const selectedPlayerId = ref(null) const displayCoords = ref<{ x: number; y: number; z: number } | null>(null) const mapid = ref(0) const contextMenu = reactive({ tile: { show: false, x: 0, y: 0, data: null }, marker: { show: false, x: 0, y: 0, data: null }, }) const coordSetFrom = ref({ x: 0, y: 0 }) const coordSet = ref({ x: 0, y: 0 }) const coordSetModalOpen = ref(false) function zoomIn(map: L.Map | null) { map?.zoomIn() } function zoomOutControl(map: L.Map | null) { map?.zoomOut() } function resetView(map: L.Map | null) { trackingCharacterId.value = -1 map?.setView([0, 0], HnHMinZoom, { animate: false }) } function updateDisplayCoords(map: L.Map | null) { if (!map) return const point = map.project(map.getCenter(), 6) displayCoords.value = { x: Math.floor(point.x / TileSize), y: Math.floor(point.y / TileSize), z: map.getZoom(), } } function toLatLng(map: L.Map | null, x: number, y: number): L.LatLng | null { return map ? map.unproject([x, y], HnHMaxZoom) : null } function closeContextMenus() { contextMenu.tile.show = false contextMenu.marker.show = false } function openTileContextMenu(clientX: number, clientY: number, coords: { x: number; y: number }) { closeContextMenus() contextMenu.tile.show = true contextMenu.tile.x = clientX contextMenu.tile.y = clientY contextMenu.tile.data = { coords } } function openMarkerContextMenu(clientX: number, clientY: number, id: number, name: string) { closeContextMenus() contextMenu.marker.show = true contextMenu.marker.x = clientX contextMenu.marker.y = clientY contextMenu.marker.data = { id, name } } function openCoordSet(coords: { x: number; y: number }) { coordSetFrom.value = { ...coords } coordSet.value = { x: coords.x, y: coords.y } coordSetModalOpen.value = true } function closeCoordSetModal() { coordSetModalOpen.value = false } const state: MapLogicState = { hideMarkers, panelCollapsed, trackingCharacterId, selectedMapId, overlayMapId, selectedMarkerId, selectedPlayerId, displayCoords, mapid, } return { state, contextMenu, coordSetFrom, coordSet, zoomIn, zoomOutControl, resetView, updateDisplayCoords, toLatLng, closeContextMenus, openTileContextMenu, openMarkerContextMenu, openCoordSet, closeCoordSetModal, coordSetModalOpen, } }