Clearing the clip is not the same as being clickable. The attribution and the pin hint are painted over the canvas and take pointer events, so a popup that ends fully inside the frame can still have its buttons underneath them. Measured at 390 on a 366x732 map: the pan cleared the clip exactly (cut 0) and a real click on Full Profile still did nothing, because at y~701 the top element at that point was div.maplibregl-ctrl-attrib-inner; on the sibling pin it was span.pin-hint-pill. Both pins panned, both looked fixed, neither was. Neither the popup nor the control is at fault. Attribution is a licence term of the basemap, so raising the popup over it is not available to us. The usable frame is simply shorter than the container, and the fit test has to say so. panPlanFor now takes a bottomInset and fits against containerH - bottomInset. On the measured case the plan changes from -77 (pan up, popup below the pin, buttons under the attribution) to +119 (pan down, popup above the pin, clear of the band) -- the planner flips direction because with the band reserved, fitting above became the smaller move. That is the existing "pick the smaller move" rule doing its job on a corrected frame, not a new rule. The inset is MEASURED from the live controls rather than assumed. A constant would be wrong on the next control we add, at a width where the attribution wraps to two lines, or when the gallery's clearance transform lifts the band. Only controls that intercept pointer events are measured: the corner container is pointer-events:none and spans nearly the full map width at 390, so measuring the container would over-reserve the whole strip. Unchanged where it was already right: a pin whose anchor fits still returns 0 (rega measured pan 0 on those in both arms), a popup taller than the usable frame still refuses rather than jumping the camera, and bottomInset 0 is byte-identical to the previous behaviour. 7 probe cases, with the post-pan fit asserted from the geometry rather than by re-calling the planner -- a self-consistent oracle cannot see an error that shifts both sides. |
||
|---|---|---|
| .. | ||
| charts | ||
| dashboards | ||
| hints | ||
| legends | ||
| map-controls | ||
| maps | ||
| poster | ||
| qa | ||
| regions | ||
| search | ||
| tables | ||
| BackToTopButton.vue | ||
| LargerScreenNotice.vue | ||
| PeopleGroupDetail.vue | ||
| README.md | ||
| ResearchMapFilterPanel.vue | ||
| ResearchMapSideMenu.vue | ||
| SideMenuDrawer.vue | ||
| ViewSelect.vue | ||
| WARNING.md | ||
library/components/ — shared Vue components
The map UI, built from parameterized pieces every app-profile reuses. Fix one here and every map benefits — never edit a shared component to customize one map.
library/components/
┌───────────────────────────────────────────┐
│ legends/ map-controls/ poster/ │
│ charts/ tables/ │
│ PeopleGroupDetail.vue SideMenuDrawer.vue │
│ ResearchMapFilterPanel.vue …SideMenu.vue │
└───────────────────────────────────────────┘
reused by every app-profile via @map/components/…
legends/,map-controls/,poster/each have their own README.- Every component uses
<script setup>, callsuseShadowStyles(), and reaches stores viainject('mapStore' | 'uiStore' | 'dataStore')— never a direct store import.
Full catalog + conventions:
../../documentation/architecture/components.md ·
per-file roles: ../../documentation/reference.md.