|
Some checks are pending
build-gate / build (push) Waiting to run
The card's first step was a gap analysis: what does the 888-line my-upg-100-list wall render that the shared component's props cannot express? Diffed both templates. They are STRUCTURALLY THE SAME — wall/tag/sub, sections with head and count, a card with "N UPG · Show on map", main with image-or-placeholder, a Print Options fieldset, the same export modal. Exactly TWO real deltas: 1. the CARD-STOCK PICKER — closed here; 2. a clickable preview image (.img.is-clickable) — still open, and small. Everything else that wall "owns" is data and taxonomy: REGION_OF, sections, fetchListRecords. That is precisely what country-posters (94 lines) and key-cities (75) already supply to this same component. `cardStocks` takes true for every stock card-render.js supports, or an array for a subset; `cardStock` remains the DEFAULT selection. Default false is today's behaviour byte-for-byte — neither migrated consumer mentions the prop and both still build. ★ LABELS ARE DERIVED FROM card-render.js STOCK, never hand-written. The 100-list carries its own DECK_STOCKS array duplicating all five labels, beneath a comment saying they "come from the renderer's own STOCK table so this list cannot drift". That was the intent, not the implementation. Deriving them makes it true, and the migration will delete the duplicate. ⚠ The import is LAZY on purpose. usePosterPrints imports card-render.js dynamically to keep a 10KB renderer out of every wall's initial bundle; importing it statically for five labels would undo that for every consumer, including the ones that show no picker at all. Options fill in when the module resolves and the <select> is not rendered until then, so there is no flash of unlabelled ids. If the configured cardStock is not among the offered stocks, the selection falls back to the first that is, rather than printing at a size the reader was never shown. buttons.cardStockAria added to ALL ELEVEN locales in the same change: check:i18n-parity still reports 0 keys of debt. An English-only key would have broken the ratchet emptied two ticks ago. VERIFIED: the derivation unit-tested against the real STOCK table — all five stocks, a subset, a subset EXCLUDING the configured default (falls back correctly), and an unknown id (dropped, not rendered blank). Not yet exercised in a browser because the picker is gated on a `records` provider and NO wall passes :records to the shared component yet — the 100-list still holds its provider in its own file. Opting country-posters in temporarily gave 0 pickers and 0 errors, which is that gate working as designed. The migration will exercise it end to end. |
||
|---|---|---|
| .. | ||
| 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.