From 4f5786ee304fc9fc383dae9583ec8f0abe40dcf2 Mon Sep 17 00:00:00 2001 From: gnezim Date: Thu, 14 May 2026 15:26:37 +0300 Subject: [PATCH] Stop map event propagation on city click --- .../flights-map/components/MapCanvas.test.tsx | 48 +++++++++++++++++++ .../flights-map/components/MapCanvas.tsx | 10 +++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/features/flights-map/components/MapCanvas.test.tsx b/src/features/flights-map/components/MapCanvas.test.tsx index 9f1f4d67..8fc03fb4 100644 --- a/src/features/flights-map/components/MapCanvas.test.tsx +++ b/src/features/flights-map/components/MapCanvas.test.tsx @@ -229,6 +229,7 @@ vi.mock("leaflet", () => { // --------------------------------------------------------------------------- import { MapCanvas } from "./MapCanvas.js"; +import L from "leaflet"; // --------------------------------------------------------------------------- // Helpers @@ -311,6 +312,53 @@ describe("MapCanvas — legacy (flat) path", () => { clickHandlers?.[0]?.({} as unknown); expect(onMarkerClick).toHaveBeenCalledWith("MOW"); }); + + it("stops tooltip pre-click events so the first city-label click is not consumed by the map", () => { + const onMarkerClick = vi.fn(); + renderCanvas( + [{ id: "MOW", lat: 1, lng: 2, style: "blue-small", label: "Москва", tooltipPermanent: true }], + { onMarkerClick }, + ); + + const marker = createdMarkers[0]; + if (!marker) { + throw new Error("expected marker to be created"); + } + + const mousedownHandlers = marker.tooltipHandlers["mousedown"]; + expect(mousedownHandlers?.length).toBeGreaterThan(0); + vi.mocked(L.DomEvent.stop).mockClear(); + mousedownHandlers?.[0]?.({} as unknown); + + expect(L.DomEvent.stop).toHaveBeenCalled(); + expect(onMarkerClick).not.toHaveBeenCalled(); + + marker.tooltipHandlers["click"]?.[0]?.({} as unknown); + expect(onMarkerClick).toHaveBeenCalledWith("MOW"); + }); + + it("stops marker click propagation before selecting the city", () => { + const onMarkerClick = vi.fn(); + renderCanvas( + [{ id: "MOW", lat: 1, lng: 2, style: "blue-small", label: "Москва", tooltipPermanent: true }], + { onMarkerClick }, + ); + + const marker = createdMarkers[0]; + if (!marker) { + throw new Error("expected marker to be created"); + } + + const markerClick = marker.on.mock.calls.find((call) => call[0] === "click")?.[1] as + | ((event: unknown) => void) + | undefined; + expect(markerClick).toBeDefined(); + vi.mocked(L.DomEvent.stop).mockClear(); + markerClick?.({}); + + expect(L.DomEvent.stop).toHaveBeenCalled(); + expect(onMarkerClick).toHaveBeenCalledWith("MOW"); + }); }); describe("MapCanvas — categorized: visibility predicate", () => { diff --git a/src/features/flights-map/components/MapCanvas.tsx b/src/features/flights-map/components/MapCanvas.tsx index bab325cf..a5fb0579 100644 --- a/src/features/flights-map/components/MapCanvas.tsx +++ b/src/features/flights-map/components/MapCanvas.tsx @@ -407,13 +407,21 @@ export const MapCanvas: FC = ({ }); const tooltip = marker.getTooltip(); + const stopTooltipEvent = (event: L.LeafletMouseEvent) => { + L.DomEvent.stop(event); + }; + tooltip?.on("mousedown", stopTooltipEvent); + tooltip?.on("mouseup", stopTooltipEvent); + tooltip?.on("dblclick", stopTooltipEvent); + tooltip?.on("preclick", stopTooltipEvent); tooltip?.on("click", (event: L.LeafletMouseEvent) => { L.DomEvent.stop(event); onMarkerClickRef.current?.(m.id); }); } - marker.on("click", () => { + marker.on("click", (event: L.LeafletMouseEvent) => { + L.DomEvent.stop(event); onMarkerClickRef.current?.(m.id); });