Typing into the research-map's search bar inside a composite (the Simple
Research dashboard) wiped the box instantly and never queried. Standalone, the
same map searched fine — which is the shape of the bug, not a coincidence.
mapbox-gl-geocoder unwraps exactly ONE shadow level to find the input:
var e = t.target && t.target.shadowRoot ? t.target.shadowRoot.activeElement : t.target
if (!(e ? e.value : "")) { this.fresh = !0, 9 !== t.keyCode && this.clear(t), ... }
Its handler is debounced, so it reads event.target after dispatch has ended, by
which time the target is the OUTERMOST host. One hop is therefore exactly right
for a map one custom element deep and exactly wrong for a map inside another
one. Measured, same build, same keystroke:
doxa-research-map (1 deep) target=DOXA-RESEARCH-MAP -> unwrap = the input -> _geocode("Bhu")
research-map-plus-grid (2) target=RESEARCH-MAP-PLUS-GRID -> unwrap = <doxa-research-map> -> clear()
An element with no .value reads as an empty box, so the vendor cleared what you
had just typed. Walk the activeElement chain to the bottom instead of one step
and hand the vendor an event whose target is that element; nesting deeper cannot
break it again, and at one level it resolves to the same input as before.
Two things worth recording. The receiver is passed explicitly: the Mapbox build
binds this method in its constructor and the MapLibre build does not, and an
unbound call landed on `this === undefined`, which swallowed the keystroke AND
the query ("Cannot read properties of undefined (reading
'_hideGeolocateButton')") — green-looking text with no search behind it. And
neither suspect on the card was the cause: the clear came from inside the vendor
bundle, not from _geoBeingCleared, and SearchBar is not involved.
MEASURED on the built tree, both engines' mapbox mode, typing "Bhutan":
fix off leaf ok (1 geocoding request) / composite value="" and 0 requests
fix on both keep "Bhutan", both fire the query, both list 19 results
including People Cluster, People Group + Country, Country and Place
Screenshot read, not just the log. gates:pre 7/7, gates:post 34/34.
|
||
|---|---|---|
| .. | ||
| charts | ||
| hints | ||
| legends | ||
| map-controls | ||
| poster | ||
| qa | ||
| search | ||
| tables | ||
| 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.