|
Some checks are pending
build-gate / build (push) Waiting to run
Last tick I found the export unreachable on mobile and recorded it as Driver-gated: "WHERE the control goes on a phone is a design call, the sheet has no titlebar". Both halves of that were wrong, and checking them was this tick. LegendMobile RENDERS SemanticTreeLegend itself — titlebar and all — and the 0x0 elements my measurement found belonged to the OTHER, hidden desktop instance mounted below the breakpoint. That geometry made it look as though the sheet had nowhere to put the control. A Driver decision was never needed. Two gaps, not one. The sheet passed neither :export-enabled nor @export, and exportEnabled defaults to false, so the control's v-if was never satisfied. Fixed via provide/inject, matching onSemanticTreeSelect immediately above it, because the sheet renders several levels down where an emit would not reach. Opt-in by construction: enabled only when a profile provides a handler. The other three LegendMobile consumers provide none and are verified untouched. Even then the export did nothing, and that second gap is the one that mattered. The profile passed :nodes but no :tabs, so hideTabs was true and the sheet showed a single flat Region tree with no tab strip — no UPG-100 Lists tab, no selectable zone, and onLegendExport bails on `if (!zoneId) return`. Passing :tabs fixed it. A :default-tab attribute was added and then removed: defaultTab is not a prop on LegendMobile, so it would have been inert. Verified end to end at 390x844: the tab strip appears, a real zone selects, Export opens, Packet clicks, and one print frame is produced. A packet on a phone. The gate written last tick — which failed on mobile by design — now passes at both widths. The newly visible mobile tabs are fully localized in en/es/zh, so catalog work from earlier ticks now reaches a surface that never showed tabs at all. Four of my own probe errors were caught by measuring rather than concluding. Clicking a REGION row left selectedKey empty, so the handler correctly bailed and it read as "export does nothing" — the same zero on DESKTOP is what proved it was the probe and not a regression. country-posters shows the same mobile gap on its own surface. Not taken; its owner's call. |
||
|---|---|---|
| .. | ||
| api | ||
| colors | ||
| components | ||
| composables | ||
| constants | ||
| data | ||
| i18n | ||
| layouts | ||
| maps | ||
| packet | ||
| scripts | ||
| stores | ||
| styles | ||
| utils | ||
| index.js | ||
| ProfileLoader.vue | ||
| README.md | ||
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.