doxa-maps/library/components/maps
Doxa Maps a71cc4b5e8 Pan the map when a popup would open half outside it
The popup is built with no explicit anchor, so the engine puts it above the pin
when there is room and below when there is not. Measured on the drop-in: a 452px
popup on a pin in the lower half of a 780px map fits NEITHER way, so it opens
below and the map's overflow:hidden cuts off the Pray and Full Profile buttons.
A real click at their centres then lands on the page behind, though a scripted
click still navigates -- so the buttons look present and are not reachable.

Moving the PIN is what makes an anchor fit, so the map pans rather than the
popup changing. Its design is untouched, which is what keeps this a clone; it is
what Leaflet does by default. The alternative, a shorter popup, would have been
a visible departure and a product decision.

The pan is the smallest one that works, and most pins need none: on a 780px map
only a narrow band moves at all, by 74px at the worst position rather than a
jump. It is animated over 200ms.

It resolves at every width this component renders at. The container is
max(780, 16/9 of width) at >=768px and twice the width below that, so even at
320px wide there is 640px of container against a 452px popup -- 164px of
headroom, and the popup would have to grow by that much before any width could
overflow. So no inner scroll and no residual case.

It returns 0 rather than panning when the popup is TALLER than its container: a
host can give the map a short slot, and there a pan would only move the clipping
around. The failure stays what it is today instead of becoming a clipped popup
and a camera that jumped. Unmeasurable inputs -- a map mid-load, a zero-height
container, an unprojectable point -- also return 0 rather than throwing, and the
pan itself is wrapped, because a pan is a nicety and must never break a click.

The offset lives in one constant now. The pan arithmetic has to use the same
number the popup was built with, and two literals drift.

Proven against the shipping function, lifted out of this file by source rather
than restated: 16 checks, including every pin position at 320, 390, 768 and
1440px wide -- none left clipped. The fit check is stated independently of the
function, because an earlier version asked the function whether it had
succeeded, and that hid a dropped offset: the pan was 12px short and its own
test 12px lax, so the two agreed while the button still clipped. Mutation-tested
four ways -- dropped offset, zeroed offset constant, flipped sign, removed
squeeze guard -- each caught.

Both consumers rebuilt: country-map +623 B, regions-dashboard +672 B.
2026-09-29 09:18:56 +00:00
..
RegionCountryMap.vue Pan the map when a popup would open half outside it 2026-09-29 09:18:56 +00:00