diff --git a/plugin-designs/country-posters/countries-map.vue b/plugin-designs/country-posters/countries-map.vue index fde9aa519..1da70ca9d 100644 --- a/plugin-designs/country-posters/countries-map.vue +++ b/plugin-designs/country-posters/countries-map.vue @@ -1262,12 +1262,30 @@ async function openPacket() { import('@map/composables/poster/useMapPoster.js'), ]) - // Same 50-group cap as before: an overnight safety limit, not a design choice. - let groups = mapData.normalizedPeopleGroups.value || [] - if (groups.length > 50) { - console.warn(`[country-posters] packet export truncated ${groups.length} → 50 people groups`) - groups = groups.slice(0, 50) - } + // ★ THE PACKET IS THE SELECTION, not the first 50 loaded groups (rega: "Asia" printed Sudan). + // library/maps/pin-selection.js reads the pins as DRAWN (their properties are derived: filled-in + // language family, canonical region keys), so a row filter would pick a plausible WRONG subset. + // This map has no dim expression, so the pins layer's own filter is the whole selection. + const all = mapData.normalizedPeopleGroups.value || [] + let groups = all + try { + const { selectedPinIds } = await import('@map/maps/pin-selection.js') + const m = map.value + const filt = m && m.getLayer('language-family-pins') ? m.getFilter('language-family-pins') : null + const ids = m ? selectedPinIds(m, { expressions: [filt].filter(Boolean) }) : null + if (ids && ids.size) { + const picked = all.filter((g) => ids.has(String(g.uniqueId ?? g.id ?? ''))) + // ids but no rows is an ID MISMATCH, not an empty selection: print everything and say so, + // rather than a packet about nothing. + if (picked.length) groups = picked + else console.warn('[country-posters] packet: the selected pins matched no rows (id mismatch); printing the full list') + } else if (ids) { + groups = [] // a genuinely empty selection: the printer's own "no records" error says so + } + } catch (e) { console.warn('[country-posters] packet selection unavailable; printing the full list:', e?.message || e) } + // Same 50-group cap as before: an overnight safety limit, not a design choice. The cover says so. + const selectedTotal = groups.length + if (groups.length > 50) groups = groups.slice(0, 50) // ★ AN EXPLICIT ADAPTER, because the two halves name the same fields differently and a mismatch // here is SILENT — the packet would print with blank names and empty photos rather than failing. @@ -1314,7 +1332,7 @@ async function openPacket() { const zone = { id: String(activeTab.value?.id || 'research-map'), - label: legendTitle.value || tabLabel(activeTab.value) || 'Doxa Map', + label: (legendTitle.value || tabLabel(activeTab.value) || 'Doxa Map') + (selectedTotal > 50 ? ` — 50 of ${selectedTotal}` : ''), zoneKey: String(activeTab.value?.id || 'research-map'), } const prints = usePosterPrints({