doxa-maps/library
Doxa Maps 63ce2d372c Wire the back-to-top on both surfaces, from the side that owns the scroller
The Driver asked for the arrow on the people-group grid and on the regions list.
Those needed different wiring, and the reason is worth recording because it is
not a preference.

The regions dashboard owns its scroller: .rd-scroll has overflow-y:auto, so the
plugin mounts the button itself and drives its own element. It deliberately does
not touch the page's scroll — this renders inside a shadow root in someone
else's page, and their scroll is not ours to move.

The people-group grid owns no scroller at all. .pgg-root sets no overflow and
.pgg-body has no rule; the grid simply grows and something outside it scrolls.
In this shell that something is .vtl-host, which lives in the layout, outside
every plugin's shadow root, so the grid could not reach it even if it should.
So the arrow for that surface belongs in the layout, beside the circle the
layout already owns, driving the pane it already owns. The grid is untouched.

.vtl-host is per tab, so the arrow follows `active` rather than binding one ref,
or it would scroll whichever pane rendered last.

One component, two consumers, and each drives a scroller it actually owns.
Checked that this adds nothing to the hardcoded-English census: 256 before, 256
after — the three regions entries there are PosterWall prop literals and predate
this.
2026-09-28 17:40:35 +00:00
..
api The people-group list is a universal prop: the same maps can show any project's list 2026-09-26 05:16:02 +00:00
charts The language tree becomes anyone's, and the numbers nobody wrote down get written down 2026-09-28 17:40:34 +00:00
colors The legends mirror now, and their labels never became their values 2026-09-26 22:06:58 +00:00
components A back-to-top that sits beside the hamburger circle, not on top of it 2026-09-28 17:40:35 +00:00
composables The packet's list becomes the profile TABLE: picture, description, three boxes 2026-09-28 16:49:01 +00:00
constants Every runtime CDN script and stylesheet is an exact version with an integrity hash 2026-09-26 05:50:24 +00:00
data Country names in the reader's language, for all 242 2026-09-27 04:14:31 +00:00
elements Five plugins were silently monolingual, because the bootstrap was copied sixteen times 2026-09-28 17:40:34 +00:00
i18n UPG Neighbor: green dots for every reached group, and each side of a neighbor pair opens the other 2026-09-28 17:40:34 +00:00
layouts Wire the back-to-top on both surfaces, from the side that owns the scroller 2026-09-28 17:40:35 +00:00
lists List names speak the reader's language: listLabel and listDefinition 2026-09-26 08:39:52 +00:00
maps The language tree becomes anyone's, and the numbers nobody wrote down get written down 2026-09-28 17:40:34 +00:00
packet The table row is a border-box, and the offline packet gets its description 2026-09-28 16:49:01 +00:00
packets Number({value:"1"}) is NaN, so the whole reachedness sentence vanished 2026-09-28 15:52:47 +00:00
scripts The whiteboard is a layer of tiered points; only the edges were ever a tree 2026-09-28 17:40:34 +00:00
stores Make the map's clustering picker real: four options, four different maps 2026-09-25 16:16:46 +00:00
styles Fiord: the MapLibre dark that actually looks like the map it replaces 2026-09-24 02:26:14 +00:00
utils A relative share link works when you click it, which is why nobody caught it 2026-09-28 17:40:34 +00:00
vendor/cldr Country names in the reader's language, for all 242 2026-09-27 04:14:31 +00:00
index.js Move internal files out of the repo; fix five dead links; a fuller delegation diagram 2026-09-25 05:14:10 +00:00
ProfileLoader.vue ?lang= on the page turns every embedded map's direction and data language, not only its text 2026-09-27 06:42:54 +00:00
README.md Complete app-profiles->plugin-designs sweep across comments/docs; build green; layouts kept at root (load-bearing) 2026-09-17 18:18:19 +00:00

library/ (@map) — the shared map template

The other half of the architecture (see ../plugin-designs/README.md): every map in plugin-designs/<your-map>/ composes the reusable, parameterized pieces that live here. Fix something here and every map benefits on the next build; break something here and every map breaks — read components/WARNING.md before touching shared pieces.

Folder What lives there
ProfileLoader.vue The root of every bundle: parses profile-config, loads the profile, provides the stores + config
components/ Shared UI — map, legends, controls, popup (PeopleGroupDetail), tables, charts, hints (README)
composables/ Shared logic — map engine (useMapInstance), provider switch, shadow-DOM styles, theming
stores/ Per-instance Pinia stores (ui / map / data) — provided by ProfileLoader, injected by children
api/ Data-source registry (sources.json) + fetch layer — the JAMstack runtime wiring
colors/ Color sets maps opt into via profile-config.colorSet
i18n/ The shared string catalogs (all maps speak the same languages)
data/ Small shared datasets baked at build time (big served data lives in ../data/)
constants/ Shared constants
scripts/ Maintainer pipelines (posters, research) — not part of any bundle

The rule of thumb (same as WARNING.md): custom code in your app-profile, reusable code here — and things only move from the first to the second once they've earned it.