doxa-maps/library
Doxa Maps 6a6950c375 Write down the contract the four dashboard panels already share
A map, a data table, a charts rail and a detail drawer behave as one dashboard
without importing each other, and nothing said how. This records the arrangement
that exists on development today; every claim in it was checked against the code
rather than remembered.

One composable provides five keys and every panel injects what it needs, with
null and {} defaults that are load-bearing: a panel rendered outside a shell must
degrade rather than throw, because a thrown setup() removes the subtree with an
empty error and no build failure.

The part worth writing down is that the bus carries two different kinds of
traffic through one generic on/emit pair. Four STATE events belong to
useSelectionBus and are emitted only by it. Seven UI events are passed through
the same bus by panels with no composable behind them. Reading the second kind as
if it were the first is how a maintainer concludes a contract is dead.

That mistake is named in the file because it has already been made twice while
auditing this kit: two panels listen for 'select' and no panel emits it, which
looks like a broken wire until you notice the emitter is the composable at
useSelectionBus.js:202. Grepping components for a bus's traffic cannot see the
bus itself.

It also records that selection is deliberately NOT reactive -- selectionSet is a
plain Set and selectionVersion is the reactive handle -- and that the charts rail
participates in filtering only, so selecting a pin does not highlight its slice.
That last one is the current contract, not an oversight: whether selection should
reach the charts is a product question and it is open.

The components stay in plugin-designs. A library component with one consumer is a
relocation rather than a promotion, and this repo has already had to move such
modules back; they graduate when a second dashboard consumes them.
2026-09-29 01:38:08 +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/whiteboard Delete 7 unreachable library components, and gate the thing a census cannot see 2026-09-29 01:38:07 +00:00
colors The legends mirror now, and their labels never became their values 2026-09-26 22:06:58 +00:00
components A band holds concentric rows, so it holds four times what I was counting 2026-09-29 01:38:08 +00:00
composables Delete 7 unreachable library components, and gate the thing a census cannot see 2026-09-29 01:38:07 +00:00
constants The poster credited Mapbox for tiles OpenFreeMap had served 2026-09-29 00:06:52 +00:00
dashboards Write down the contract the four dashboard panels already share 2026-09-29 01:38:08 +00:00
data Country names in the reader's language, for all 242 2026-09-27 04:14:31 +00:00
elements Twenty-four warnings about an overwrite that was the whole point 2026-09-28 17:53:38 +00:00
i18n A country map you can drop on one page, without the dashboard around it 2026-09-29 01:38:07 +00:00
layouts Every animating library component now honours prefers-reduced-motion itself 2026-09-29 01:38:07 +00:00
lists List names speak the reader's language: listLabel and listDefinition 2026-09-26 08:39:52 +00:00
maps The poster credited Mapbox for tiles OpenFreeMap had served 2026-09-29 00:06:52 +00:00
packet Put the missing-map sentence in every packet language 2026-09-29 00:59:14 +00:00
packets Number({value:"1"}) is NaN, so the whole reachedness sentence vanished 2026-09-28 15:52:47 +00:00
scripts Put the missing-map sentence in every packet language 2026-09-29 00:59:14 +00:00
stores Make the map's clustering picker real: four options, four different maps 2026-09-25 16:16:46 +00:00
styles Share the ported _globals.scss rules through one module 2026-09-29 01:38:08 +00:00
utils A country map you can drop on one page, without the dashboard around it 2026-09-29 01:38:07 +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.