89 lines
3.9 KiB
JavaScript
89 lines
3.9 KiB
JavaScript
/**
|
|
* plugin-designs/country-posters/index.js
|
|
*
|
|
* Bundle entry — registers the country-posters web component.
|
|
*
|
|
* Registers ONE custom-element tag:
|
|
* - <country-posters-map>
|
|
*
|
|
* Usage from a host page:
|
|
* <script src="/app/country-posters.js"></script>
|
|
* <country-posters-map profile-config='{"profile":"countries-map","tk":"pk.YOUR_MAPBOX_TOKEN"}'></country-posters-map>
|
|
* <country-posters-map profile-config='{"profile":"country-poster-wall"}'></country-posters-map>
|
|
*
|
|
* TWO PROFILES, ONE BUNDLE — the same shape as my-upg-100-list:
|
|
* countries-map.vue the map; legend opens on the COUNTRY level
|
|
* country-poster-wall.vue the poster grid, grouped by region, collapsible
|
|
*
|
|
* WHY A SEPARATE BUNDLE rather than two more profiles in my-upg-100-list:
|
|
* > design note 2026-08-01: "I don't mind creating multiple application profiles, one
|
|
* > for each application. I do mind that we really need to make sure every
|
|
* > component that we're [re]usable is added to the library."
|
|
* PROFILES duplicate; COMPONENTS get promoted to library/ and parameterized. The
|
|
* wall here is @map/components/poster/PosterWall.vue — the same component the
|
|
* 100-list renders — differing only in data, taxonomy and copy.
|
|
*
|
|
* Profile registry — ProfileLoader lives inside @map and cannot use
|
|
* import.meta.glob to reach into a bundle's folder. The bundle MUST evaluate
|
|
* import.meta.glob('./*.vue') locally and hand the result to the loader via
|
|
* app.provide('profileModules', ...).
|
|
*/
|
|
|
|
import { defineCustomElement } from 'vue'
|
|
import { createPinia } from 'pinia'
|
|
import ProfileLoader from '@map/ProfileLoader.vue'
|
|
import { createAppI18n } from '@map/i18n/index.js'
|
|
import { registerStrategies } from '@map/colors/_registry.js'
|
|
|
|
// ─── Bundle-private profile registry ─────────────────────────────────────────
|
|
const profileModules = import.meta.glob('./*.vue')
|
|
|
|
// ─── Bundle-private color strategies ─────────────────────────────────────────
|
|
// COPIED VERBATIM from doxa-research-map/src/colors/ — affinity-block.js,
|
|
// doxa-region.js, resource.js. countries-map.vue is a clone of research-map.vue,
|
|
// so it needs the same three research-only strategies; without doxaRegion in
|
|
// particular the Countries tab would silently fall back to a different palette
|
|
// (getColorStrategy() fails soft, so the symptom is wrong colours, not an error).
|
|
//
|
|
// Keys are auto-derived from filenames and merged OVER the shared library set.
|
|
// This bundle inlines its own copy of the registry (IIFE build), so registering
|
|
// here affects THIS bundle only.
|
|
registerStrategies(import.meta.glob('./src/colors/*.js', { eager: true }))
|
|
|
|
// ─── Mapbox RTL text plugin — load ONCE before any map instance ──────────────
|
|
if (typeof window !== 'undefined' && window.mapboxgl?.setRTLTextPlugin) {
|
|
try {
|
|
window.mapboxgl.setRTLTextPlugin(
|
|
'https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.3.0/mapbox-gl-rtl-text.js',
|
|
null,
|
|
true // lazy
|
|
)
|
|
} catch (_) {
|
|
// Plugin already set in this session — ignore.
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Each instance gets its own Pinia + i18n so multiple embeds on one page never
|
|
* bleed state into each other.
|
|
*/
|
|
function buildCountryPostersElement() {
|
|
return defineCustomElement(ProfileLoader, {
|
|
configureApp(app) {
|
|
app.use(createPinia())
|
|
app.use(createAppI18n())
|
|
app.provide('profileModules', profileModules)
|
|
}
|
|
})
|
|
}
|
|
|
|
const CountryPostersElement = buildCountryPostersElement()
|
|
|
|
// Guard prevents "already registered" errors when this IIFE is loaded twice.
|
|
if (typeof customElements !== 'undefined') {
|
|
if (!customElements.get('country-posters-map')) {
|
|
customElements.define('country-posters-map', CountryPostersElement)
|
|
}
|
|
}
|
|
|
|
export default CountryPostersElement
|