Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions

This commit is contained in:
Doxa Maps 2026-09-26 01:53:48 +00:00
commit d8b3541865
19 changed files with 289 additions and 123 deletions

View file

@ -39,6 +39,19 @@ import { ref, reactive, watch, computed, onMounted, getCurrentInstance } from 'v
// SHARED search primitives (one source of truth for BOTH cap-2 grid + cap-1 dashboard).
import SearchBar from '@map/components/search/SearchBar.vue'
import FilterDropdown from '@map/components/search/FilterDropdown.vue'
import { tStatic } from '@map/i18n/index.js'
// ★ THIS HEADER HAD NO i18n AT ALL, and it is the top of Big Picture. Every label below was an
// English literal passed as a PROP — FilterDropdown itself translates nothing, it renders what the
// caller hands it, so a perfectly localized component showed "Region" on an Arabic page. Read
// through tStatic rather than useI18n, for the reason the rest of this tree gives: these components
// mount inside custom elements that install no i18n plugin, and an unguarded useI18n() throws on
// the way in and takes the whole header with it.
//
// The grid namespace first, because this header drives the cap-2 grid and its sibling reads the
// same keys; dashboard.* second; the English literal last, so a missing key degrades to what
// shipped rather than to a key name.
const L = (key, en) => tStatic('grid.' + key) || tStatic('dashboard.' + key) || en
const props = defineProps({
// live count of matched groups, pushed back down by the composite for display.
@ -160,22 +173,22 @@ onMounted(loadOptions)
<!-- The FOUR SHARED FilterDropdowns (replace the two native <select>s). -->
<div class="rh-controls">
<FilterDropdown
label="Region" name="wagf_region"
:label="L('wagf_region', 'Region')" name="wagf_region"
:options="options.wagf_region" :value="sel.wagf_region"
@filter-change="onFilterChange" @filter-clear="onFilterClear"
/>
<FilterDropdown
label="Bloc" name="wagf_block"
:label="L('wagf_block', 'Bloc')" name="wagf_block"
:options="options.wagf_block" :value="sel.wagf_block"
@filter-change="onFilterChange" @filter-clear="onFilterClear"
/>
<FilterDropdown
label="People Group" name="rop1"
:label="L('rop1', 'People Group')" name="rop1"
:options="options.rop1" :value="sel.rop1"
@filter-change="onFilterChange" @filter-clear="onFilterClear"
/>
<FilterDropdown
label="Religion" name="religion"
:label="L('religion', 'Religion')" name="religion"
:options="options.religion" :value="sel.religion"
@filter-change="onFilterChange" @filter-clear="onFilterClear"
/>
@ -185,7 +198,7 @@ onMounted(loadOptions)
type="button"
aria-label="Reset all filters and search"
@click="reset"
>Reset</button>
>{{ L('reset_all', '') || tStatic('controls.reset_all') || 'Reset' }}</button>
</div>
</div>
</template>

View file

@ -13,7 +13,7 @@
* Same "import the REAL components, no fork" discipline as big-picture: the grid is the exact
* people-groups-grid component; the dashboard is the exact research-dashboard component.
*/
import { reactive, provide, inject, ref, computed, watchEffect } from 'vue'
import { reactive, provide, inject, ref, computed, watchEffect, watch, onMounted, getCurrentInstance } from 'vue'
import { SUPPORTED_LOCALES, setRuntimeLocale } from '@map/i18n/index.js'
import { resolveEmbedBase } from '@map/utils/embedBase.js'
import { useSharedMapToken, publishMapToken } from '@map/composables/useSharedMapToken.js'
@ -282,6 +282,31 @@ const hostLang = computed(() => {
})
watchEffect(() => { if (hostLang.value) setRuntimeLocale(hostLang.value) })
// ★ RTL IS A DIRECTION, NOT A TRANSLATION, and nothing was setting it here.
// createAppI18n reflects an RTL locale onto document.documentElement — right for a leaf page it
// owns, useless for an element dropped into somebody else's page, which is the case this composite
// exists for. A host that asks for Arabic through profile-config got Arabic WORDS in a
// left-to-right layout: readable glyphs in the wrong place, which reads as a styling quirk rather
// than the bug it is.
//
// Set on the custom-element HOST rather than on the layout inside it, deliberately: `dir` takes
// effect through the inherited CSS `direction`, and inheritance crosses shadow boundaries — so one
// attribute on the host covers this composite's own chrome AND every nested element beneath it,
// which is the half the audit found missing. Only ever SET, never cleared: a host page that already
// declares its own dir owns that decision.
const textDir = computed(() => {
const l = hostLang.value || getRuntimeLocale() || detectLocale()
return RTL_LOCALES.has(l) ? 'rtl' : 'ltr'
})
function reflectDir() {
try {
const host = getCurrentInstance()?.proxy?.$el?.getRootNode?.()?.host
if (host && textDir.value === 'rtl') host.setAttribute('dir', 'rtl')
} catch (_) { /* no host (SSR/tests) — nothing to reflect */ }
}
onMounted(reflectDir)
watch(textDir, reflectDir)
// ★ AND PROVIDE IT THE WAY ProfileLoader WOULD. This composite bakes its children in rather than
// mounting them through ProfileLoader, and ProfileLoader is the ONLY provider of 'mapboxToken' in
// the repo — so DashboardMapPanel's inject('mapboxToken', ref('')) fell through to its empty

View file

@ -2036,6 +2036,28 @@ watch(() => profileConfig?.value?.externalFilters, (raw) => {
// every pin because the host said something this map cannot express is worse than doing nothing.
}
// ★ FIT THE CAMERA TO WHAT THE LIST IS SHOWING (BUILD-GRID-SELECTION-FLIES-THE-MAP).
// The link ran one way: a choice on the map narrowed the grid, and a choice in the grid moved
// nothing — a reader who filtered the list to 83 peoples had no idea where they were. The
// composite sends the slugs its grid is currently showing and this map frames them, using the
// coordinates it already holds. Slugs and not a bbox because the composite has no coordinates;
// this half is the one that knows where anything is.
//
// CAMERA POLICY COPIED, DELIBERATELY, from research-dashboard's useSelectionCamera.js, which
// worked all of this out for the desktop pair: a single row has a zero-area bbox and would fit
// at street level for what is really a country-scale centroid; several rows in one place are
// the same problem by another route; and a selection spanning most of the globe animates the
// wrong way around the antimeridian if framed literally. The right end state is ONE shared
// composable in library/, not two copies — but a library move cannot be landed from this lane
// under the current rule, so it is cited rather than imported, and a move later should delete
// this block rather than leave a third copy.
//
// ⚠ MOTION SAFETY. The Driver is photosensitive, and a camera that re-animates on every
// keystroke of a search box is exactly the strobe class this repo has already paid for. One
// move per settled set: an identical slug set never re-flies, and a reduced-motion preference
// JUMPS (duration 0) rather than easing — same destination, no traversal.
if ('fitSlugs' in raw) applyFitSlugs(raw.fitSlugs)
// Language needs no translation — MEASURED, this map's own vocabulary is display names
// ('Abai Sungai', 'Afar', 'Afrikaans'), the same strings a people-group grid shows for
// primary_language. Verified rather than assumed, because religion just above is the counter-example.
@ -2183,6 +2205,65 @@ watch(() => uiStore.religionFilter, (key) => {
else applyDimFilter({ kind: null })
})
// ─── FIT THE MAP TO A SET OF PEOPLES (see the fitSlugs note in the externalFilters watcher) ───
const FIT_PADDING_PX = 70
const FIT_MAX_ZOOM = 5.5 // several peoples: stop at regional framing, never street level
const SINGLE_ROW_ZOOM = 6 // one people group: its coordinate is a country-scale centroid
const DEGENERATE_SPAN_DEG = 0.01 // a cluster this tight is a point by another route
const WIDE_SPAN_DEG = 110 // past this the set wraps the globe; frame the world instead
const WORLD_ZOOM = 1.45
const FLY_DURATION_MS = 900
let _lastFitKey = ''
function prefersReducedMotion() {
try {
return typeof window !== 'undefined'
&& typeof window.matchMedia === 'function'
&& window.matchMedia('(prefers-reduced-motion: reduce)').matches
} catch (_) { return false }
}
function applyFitSlugs(slugs) {
const list = Array.isArray(slugs) ? slugs.filter((s) => typeof s === 'string' && s) : []
// An identical set must not re-animate: the grid re-emits on every keystroke and every re-render,
// and re-flying to the same place is motion with no information in it.
const key = list.length ? `${list.length}:${list[0]}:${list[list.length - 1]}` : ''
if (key === _lastFitKey) return
_lastFitKey = key
if (!list.length) return
const want = new Set(list)
const rows = mapData?.normalizedPeopleGroups?.value || []
let minLng = Infinity, minLat = Infinity, maxLng = -Infinity, maxLat = -Infinity, n = 0
for (const r of rows) {
if (!r || !want.has(r.slug)) continue
// The live API returns coordinates as STRINGS, so every read goes through Number() — a raw
// string compare orders "9.5" above "78.2" and silently produces a wrong bbox.
const lng = Number(r.longitude ?? r.lng)
const lat = Number(r.latitude ?? r.lat)
if (!Number.isFinite(lng) || !Number.isFinite(lat)) continue
if (lng < minLng) minLng = lng
if (lat < minLat) minLat = lat
if (lng > maxLng) maxLng = lng
if (lat > maxLat) maxLat = lat
n++
}
if (!n) return // nothing this map holds — say nothing rather than fly nowhere
const duration = prefersReducedMotion() ? 0 : FLY_DURATION_MS
const spanLng = maxLng - minLng
const spanLat = maxLat - minLat
if (spanLng > WIDE_SPAN_DEG) {
mapFly.flyToCoords?.({ longitude: (minLng + maxLng) / 2, latitude: (minLat + maxLat) / 2 }, WORLD_ZOOM, { duration })
return
}
if (n === 1 || (spanLng < DEGENERATE_SPAN_DEG && spanLat < DEGENERATE_SPAN_DEG)) {
mapFly.flyToCoords?.({ longitude: minLng, latitude: minLat }, SINGLE_ROW_ZOOM, { duration })
return
}
mapFly.fitBounds?.([[minLng, minLat], [maxLng, maxLat]], FIT_PADDING_PX, { maxZoom: FIT_MAX_ZOOM, duration })
}
// ─── Clusters wiring: TWO CONTROLS, ONE STATE ────────────────────────────────
// This map has two ways to ask for clustering and they used to disagree:
//

View file

@ -55,7 +55,7 @@
* ON via prop. This is why the swap-inside-one-element idea was genuinely complex: the two top
* elements do not merely look different, they imply OPPOSITE control ownership below.
*/
import { computed, reactive, watch, onMounted, onBeforeUnmount, getCurrentInstance, watchEffect } from 'vue'
import { computed, reactive, watch, onMounted, onBeforeUnmount, getCurrentInstance, watchEffect, ref } from 'vue'
import { SUPPORTED_LOCALES, setRuntimeLocale } from '@map/i18n/index.js'
import StackLayout from '@map/layouts/StackLayout.vue'
import { resolveEmbedBase } from '@map/utils/embedBase.js'
@ -127,6 +127,31 @@ const hostLang = computed(() => {
})
watchEffect(() => { if (hostLang.value) setRuntimeLocale(hostLang.value) })
// ★ RTL IS A DIRECTION, NOT A TRANSLATION, and nothing was setting it here.
// createAppI18n reflects an RTL locale onto document.documentElement — right for a leaf page it
// owns, useless for an element dropped into somebody else's page, which is the case this composite
// exists for. A host that asks for Arabic through profile-config got Arabic WORDS in a
// left-to-right layout: readable glyphs in the wrong place, which reads as a styling quirk rather
// than the bug it is.
//
// Set on the custom-element HOST rather than on the layout inside it, deliberately: `dir` takes
// effect through the inherited CSS `direction`, and inheritance crosses shadow boundaries — so one
// attribute on the host covers this composite's own chrome AND every nested element beneath it,
// which is the half the audit found missing. Only ever SET, never cleared: a host page that already
// declares its own dir owns that decision.
const textDir = computed(() => {
const l = hostLang.value || getRuntimeLocale() || detectLocale()
return RTL_LOCALES.has(l) ? 'rtl' : 'ltr'
})
function reflectDir() {
try {
const host = getCurrentInstance()?.proxy?.$el?.getRootNode?.()?.host
if (host && textDir.value === 'rtl') host.setAttribute('dir', 'rtl')
} catch (_) { /* no host (SSR/tests) — nothing to reflect */ }
}
onMounted(reflectDir)
watch(textDir, reflectDir)
// The absolute url this composite is shared and iframed as. Built here rather than written as a
// literal because resolveEmbedBase() walks profileConfig.embedBaseUrl → window.MAP_EMBED_BASE_URL →
// the root this bundle derives from its OWN script url, so the link is right on doxa.life, on
@ -202,6 +227,20 @@ const bundleSrc = (bundle, file) =>
// cannot resolve and the reader cannot see. So the composite mirrors the map's own exclusivity: a
// new facet replaces the previous one, exactly as clicking a second legend row does.
const linked = reactive({ region: { value: '', label: '' }, religion: '', language: '' })
// ★ WHAT THE LIST IS SHOWING, so the map can go there (BUILD-GRID-SELECTION-FLIES-THE-MAP).
// The link ran one way: the map narrowed the grid, and the grid moved nothing. The grid already
// reports the slugs it is showing on every `groups-filtered`, so the honest wire is the one that
// already exists — no new control, and a grid mounted alone still emits into a room with no
// listener. This composite does not know where any people group IS; the map does, so it gets the
// slugs and frames them itself.
//
// CAPPED, and the cap is the point rather than a performance worry: a set this large is not a
// selection, it is "almost everything", and framing it would swing the camera to a world view that
// tells the reader nothing while moving a lot. Below the cap the set is specific enough that seeing
// where it sits is the whole value.
const FIT_MAX_SLUGS = 400
const gridSlugs = ref([])
function clearExcept(keep) {
if (keep !== 'region' && (linked.region.value || linked.region.label)) { linked.region.value = ''; linked.region.label = '' }
if (keep !== 'religion' && linked.religion) linked.religion = ''
@ -250,6 +289,11 @@ function onGridFiltered(ev) {
if (pushing) return
// The grid's activeFilters carry { value, label } per facet — exactly the two forms the two
// halves need, which is why this reads both rather than picking one.
// The slugs travel even when the facets are unchanged: a search term narrows the list without
// touching any facet, and that is exactly a case where the reader wants the map to follow.
const slugs = Array.isArray(ev?.detail?.slugs) ? ev.detail.slugs : []
gridSlugs.value = slugs.length && slugs.length <= FIT_MAX_SLUGS ? slugs : []
const active = ev?.detail?.activeFilters || {}
const entry = active.wagf_region
// Religion and language travel as the NAME, which for this grid is the option's label — the same
@ -291,7 +335,7 @@ function pushToChildren() {
if (map) {
let cfg = {}
try { cfg = JSON.parse(map.getAttribute('profile-config') || '{}') } catch (_) { cfg = {} }
cfg.externalFilters = { region: linked.region.value, religion: linked.religion, language: linked.language }
cfg.externalFilters = { region: linked.region.value, religion: linked.religion, language: linked.language, fitSlugs: gridSlugs.value }
map.setAttribute('profile-config', JSON.stringify(cfg))
}
const grid = rootEl.querySelector('people-groups-grid')
@ -302,6 +346,9 @@ function pushToChildren() {
}
}
watch(linked, pushToChildren, { deep: true })
// The slug set changes without any facet changing (a search term, a cleared filter), so it needs
// its own trigger — `linked` alone would leave the camera behind.
watch(gridSlugs, pushToChildren)
onMounted(() => {
rootEl = getCurrentInstance()?.proxy?.$el?.getRootNode?.() || null
@ -373,7 +420,7 @@ const sections = computed(() => [
...(hostProvider.value ? { provider: hostProvider.value } : {}),
...(hostLang.value ? { lang: hostLang.value } : {}),
// The composite's filter state, in the map's inbound shape. Absent keys are ignored there.
externalFilters: { region: linked.region.value, religion: linked.religion, language: linked.language },
externalFilters: { region: linked.region.value, religion: linked.religion, language: linked.language, fitSlugs: gridSlugs.value },
assetsBase: '../../assets',
shareUrl: SHARE_URL
})

File diff suppressed because one or more lines are too long

View file

@ -37,7 +37,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <bp-big-picture> custom element. -->
<script src="../../big-picture.js" integrity="sha384-pmc+jltlmIQtPfiI/n9rmjWAZlRd3SVPkTUjJpbv8BNAKC+S6PHyS9Z4YqeIwolQ" crossorigin="anonymous"></script>
<script src="../../big-picture.js" integrity="sha384-QkfaEQm7mpCC6VsaiEd+DAQEooG2EbLAL17qM5IHa6gejWy0p2thXkShsnbQXDW0" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -37,7 +37,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <bp-big-picture> custom element. -->
<script src="../../big-picture.js" integrity="sha384-pmc+jltlmIQtPfiI/n9rmjWAZlRd3SVPkTUjJpbv8BNAKC+S6PHyS9Z4YqeIwolQ" crossorigin="anonymous"></script>
<script src="../../big-picture.js" integrity="sha384-QkfaEQm7mpCC6VsaiEd+DAQEooG2EbLAL17qM5IHa6gejWy0p2thXkShsnbQXDW0" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -37,7 +37,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <bp-big-picture> custom element. -->
<script src="../big-picture.js" integrity="sha384-pmc+jltlmIQtPfiI/n9rmjWAZlRd3SVPkTUjJpbv8BNAKC+S6PHyS9Z4YqeIwolQ" crossorigin="anonymous"></script>
<script src="../big-picture.js" integrity="sha384-QkfaEQm7mpCC6VsaiEd+DAQEooG2EbLAL17qM5IHa6gejWy0p2thXkShsnbQXDW0" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -41,7 +41,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <dashboard-plus-grid> custom element. -->
<script src="../../dashboard-plus-grid.js" integrity="sha384-L6zSKq1tvgdy6CLFedrkA+q9WdLdEtnwe2JCSZBHikYv82IakJTX4kRfkKe9ENIY" crossorigin="anonymous"></script>
<script src="../../dashboard-plus-grid.js" integrity="sha384-stZQxboxwi/L6KrgqgqBx1RSdYtc4JhSz7g9Lf+DA7x3SKP2v8UpDRmDmG6O++8G" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -41,7 +41,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <dashboard-plus-grid> custom element. -->
<script src="../dashboard-plus-grid.js" integrity="sha384-L6zSKq1tvgdy6CLFedrkA+q9WdLdEtnwe2JCSZBHikYv82IakJTX4kRfkKe9ENIY" crossorigin="anonymous"></script>
<script src="../dashboard-plus-grid.js" integrity="sha384-stZQxboxwi/L6KrgqgqBx1RSdYtc4JhSz7g9Lf+DA7x3SKP2v8UpDRmDmG6O++8G" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -39,7 +39,7 @@
"bundle": "big-picture",
"scriptUrl": "./big-picture/big-picture.js",
"output": "dx-maps/big-picture/big-picture.js",
"integrity": "sha384-pmc+jltlmIQtPfiI/n9rmjWAZlRd3SVPkTUjJpbv8BNAKC+S6PHyS9Z4YqeIwolQ",
"integrity": "sha384-QkfaEQm7mpCC6VsaiEd+DAQEooG2EbLAL17qM5IHa6gejWy0p2thXkShsnbQXDW0",
"elements": [
"bp-big-picture",
"bp-research-header",
@ -61,7 +61,7 @@
"scriptUrl": "./big-picture/big-picture.js",
"embed": {
"iframe": "<iframe src=\"./big-picture/big-picture/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./big-picture/big-picture.js\" integrity=\"sha384-pmc+jltlmIQtPfiI/n9rmjWAZlRd3SVPkTUjJpbv8BNAKC+S6PHyS9Z4YqeIwolQ\" crossorigin=\"anonymous\"></script>\n<bp-big-picture profile-config='{\"profile\":\"big-picture\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></bp-big-picture>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./big-picture/big-picture.js\" integrity=\"sha384-QkfaEQm7mpCC6VsaiEd+DAQEooG2EbLAL17qM5IHa6gejWy0p2thXkShsnbQXDW0\" crossorigin=\"anonymous\"></script>\n<bp-big-picture profile-config='{\"profile\":\"big-picture\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></bp-big-picture>"
},
"instances": [
{
@ -215,7 +215,7 @@
"bundle": "dashboard-plus-grid",
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
"output": "dx-maps/dashboard-plus-grid/dashboard-plus-grid.js",
"integrity": "sha384-L6zSKq1tvgdy6CLFedrkA+q9WdLdEtnwe2JCSZBHikYv82IakJTX4kRfkKe9ENIY",
"integrity": "sha384-stZQxboxwi/L6KrgqgqBx1RSdYtc4JhSz7g9Lf+DA7x3SKP2v8UpDRmDmG6O++8G",
"elements": [
"dashboard-plus-grid"
],
@ -235,7 +235,7 @@
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
"embed": {
"iframe": "<iframe src=\"./dashboard-plus-grid/dashboard-plus-grid/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-L6zSKq1tvgdy6CLFedrkA+q9WdLdEtnwe2JCSZBHikYv82IakJTX4kRfkKe9ENIY\" crossorigin=\"anonymous\"></script>\n<dashboard-plus-grid profile-config='{\"profile\":\"dashboard-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></dashboard-plus-grid>"
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-stZQxboxwi/L6KrgqgqBx1RSdYtc4JhSz7g9Lf+DA7x3SKP2v8UpDRmDmG6O++8G\" crossorigin=\"anonymous\"></script>\n<dashboard-plus-grid profile-config='{\"profile\":\"dashboard-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></dashboard-plus-grid>"
},
"instances": [
{
@ -354,7 +354,7 @@
"bundle": "doxa-research-map",
"scriptUrl": "./doxa-research-map/doxa-research-map.js",
"output": "dx-maps/doxa-research-map/doxa-research-map.js",
"integrity": "sha384-N3gXkdDxxB9NTvUTGajmPBFLpGwKNe1Z0IjT7LspYBMDBmVxGSmsWg72WRyGAhyg",
"integrity": "sha384-Kba3/FZ8v1VrckuPXnzh/jWs0p6RaydyydEbEIgw+jSSVlCGUbvowdHN2YMSrxiE",
"elements": [
"doxa-research-map"
],
@ -370,7 +370,7 @@
"scriptUrl": "./doxa-research-map/doxa-research-map.js",
"embed": {
"iframe": "<iframe src=\"./doxa-research-map/research-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-research-map/doxa-research-map.js\" integrity=\"sha384-N3gXkdDxxB9NTvUTGajmPBFLpGwKNe1Z0IjT7LspYBMDBmVxGSmsWg72WRyGAhyg\" crossorigin=\"anonymous\"></script>\n<doxa-research-map profile-config='{\"profile\":\"research-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-research-map>"
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-research-map/doxa-research-map.js\" integrity=\"sha384-Kba3/FZ8v1VrckuPXnzh/jWs0p6RaydyydEbEIgw+jSSVlCGUbvowdHN2YMSrxiE\" crossorigin=\"anonymous\"></script>\n<doxa-research-map profile-config='{\"profile\":\"research-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-research-map>"
},
"instances": [
{
@ -971,7 +971,7 @@
"bundle": "research-map-plus-grid",
"scriptUrl": "./research-map-plus-grid/research-map-plus-grid.js",
"output": "dx-maps/research-map-plus-grid/research-map-plus-grid.js",
"integrity": "sha384-N12PTsk2HVN2Uh9nhF1R74uZ8+YO1nz92CqD+wlWhq5D+dKdaGy7BUr5QwaHg9C2",
"integrity": "sha384-nlzCq4Er6WPMedck7D5qAXa27wpbd75WI40/BlOhDA4ZKHgud1lhxfJWvy0bpFTA",
"elements": [
"research-map-plus-grid"
],
@ -991,7 +991,7 @@
"scriptUrl": "./research-map-plus-grid/research-map-plus-grid.js",
"embed": {
"iframe": "<iframe src=\"./research-map-plus-grid/research-map-plus-grid/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-map-plus-grid/research-map-plus-grid.js\" integrity=\"sha384-N12PTsk2HVN2Uh9nhF1R74uZ8+YO1nz92CqD+wlWhq5D+dKdaGy7BUr5QwaHg9C2\" crossorigin=\"anonymous\"></script>\n<research-map-plus-grid profile-config='{\"profile\":\"research-map-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-map-plus-grid>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-map-plus-grid/research-map-plus-grid.js\" integrity=\"sha384-nlzCq4Er6WPMedck7D5qAXa27wpbd75WI40/BlOhDA4ZKHgud1lhxfJWvy0bpFTA\" crossorigin=\"anonymous\"></script>\n<research-map-plus-grid profile-config='{\"profile\":\"research-map-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-map-plus-grid>"
},
"instances": [
{

File diff suppressed because one or more lines are too long

View file

@ -30,7 +30,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <doxa-research-map> custom element. -->
<script src="../doxa-research-map.js" integrity="sha384-N3gXkdDxxB9NTvUTGajmPBFLpGwKNe1Z0IjT7LspYBMDBmVxGSmsWg72WRyGAhyg" crossorigin="anonymous"></script>
<script src="../doxa-research-map.js" integrity="sha384-Kba3/FZ8v1VrckuPXnzh/jWs0p6RaydyydEbEIgw+jSSVlCGUbvowdHN2YMSrxiE" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -27,7 +27,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <doxa-research-map> custom element. -->
<script src="../../doxa-research-map.js" integrity="sha384-N3gXkdDxxB9NTvUTGajmPBFLpGwKNe1Z0IjT7LspYBMDBmVxGSmsWg72WRyGAhyg" crossorigin="anonymous"></script>
<script src="../../doxa-research-map.js" integrity="sha384-Kba3/FZ8v1VrckuPXnzh/jWs0p6RaydyydEbEIgw+jSSVlCGUbvowdHN2YMSrxiE" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -39,7 +39,7 @@
"bundle": "big-picture",
"scriptUrl": "./big-picture/big-picture.js",
"output": "dx-maps/big-picture/big-picture.js",
"integrity": "sha384-pmc+jltlmIQtPfiI/n9rmjWAZlRd3SVPkTUjJpbv8BNAKC+S6PHyS9Z4YqeIwolQ",
"integrity": "sha384-QkfaEQm7mpCC6VsaiEd+DAQEooG2EbLAL17qM5IHa6gejWy0p2thXkShsnbQXDW0",
"elements": [
"bp-big-picture",
"bp-research-header",
@ -61,7 +61,7 @@
"scriptUrl": "./big-picture/big-picture.js",
"embed": {
"iframe": "<iframe src=\"./big-picture/big-picture/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./big-picture/big-picture.js\" integrity=\"sha384-pmc+jltlmIQtPfiI/n9rmjWAZlRd3SVPkTUjJpbv8BNAKC+S6PHyS9Z4YqeIwolQ\" crossorigin=\"anonymous\"></script>\n<bp-big-picture profile-config='{\"profile\":\"big-picture\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></bp-big-picture>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./big-picture/big-picture.js\" integrity=\"sha384-QkfaEQm7mpCC6VsaiEd+DAQEooG2EbLAL17qM5IHa6gejWy0p2thXkShsnbQXDW0\" crossorigin=\"anonymous\"></script>\n<bp-big-picture profile-config='{\"profile\":\"big-picture\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></bp-big-picture>"
},
"instances": [
{
@ -215,7 +215,7 @@
"bundle": "dashboard-plus-grid",
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
"output": "dx-maps/dashboard-plus-grid/dashboard-plus-grid.js",
"integrity": "sha384-L6zSKq1tvgdy6CLFedrkA+q9WdLdEtnwe2JCSZBHikYv82IakJTX4kRfkKe9ENIY",
"integrity": "sha384-stZQxboxwi/L6KrgqgqBx1RSdYtc4JhSz7g9Lf+DA7x3SKP2v8UpDRmDmG6O++8G",
"elements": [
"dashboard-plus-grid"
],
@ -235,7 +235,7 @@
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
"embed": {
"iframe": "<iframe src=\"./dashboard-plus-grid/dashboard-plus-grid/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-L6zSKq1tvgdy6CLFedrkA+q9WdLdEtnwe2JCSZBHikYv82IakJTX4kRfkKe9ENIY\" crossorigin=\"anonymous\"></script>\n<dashboard-plus-grid profile-config='{\"profile\":\"dashboard-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></dashboard-plus-grid>"
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-stZQxboxwi/L6KrgqgqBx1RSdYtc4JhSz7g9Lf+DA7x3SKP2v8UpDRmDmG6O++8G\" crossorigin=\"anonymous\"></script>\n<dashboard-plus-grid profile-config='{\"profile\":\"dashboard-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></dashboard-plus-grid>"
},
"instances": [
{
@ -354,7 +354,7 @@
"bundle": "doxa-research-map",
"scriptUrl": "./doxa-research-map/doxa-research-map.js",
"output": "dx-maps/doxa-research-map/doxa-research-map.js",
"integrity": "sha384-N3gXkdDxxB9NTvUTGajmPBFLpGwKNe1Z0IjT7LspYBMDBmVxGSmsWg72WRyGAhyg",
"integrity": "sha384-Kba3/FZ8v1VrckuPXnzh/jWs0p6RaydyydEbEIgw+jSSVlCGUbvowdHN2YMSrxiE",
"elements": [
"doxa-research-map"
],
@ -370,7 +370,7 @@
"scriptUrl": "./doxa-research-map/doxa-research-map.js",
"embed": {
"iframe": "<iframe src=\"./doxa-research-map/research-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-research-map/doxa-research-map.js\" integrity=\"sha384-N3gXkdDxxB9NTvUTGajmPBFLpGwKNe1Z0IjT7LspYBMDBmVxGSmsWg72WRyGAhyg\" crossorigin=\"anonymous\"></script>\n<doxa-research-map profile-config='{\"profile\":\"research-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-research-map>"
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-research-map/doxa-research-map.js\" integrity=\"sha384-Kba3/FZ8v1VrckuPXnzh/jWs0p6RaydyydEbEIgw+jSSVlCGUbvowdHN2YMSrxiE\" crossorigin=\"anonymous\"></script>\n<doxa-research-map profile-config='{\"profile\":\"research-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-research-map>"
},
"instances": [
{
@ -971,7 +971,7 @@
"bundle": "research-map-plus-grid",
"scriptUrl": "./research-map-plus-grid/research-map-plus-grid.js",
"output": "dx-maps/research-map-plus-grid/research-map-plus-grid.js",
"integrity": "sha384-N12PTsk2HVN2Uh9nhF1R74uZ8+YO1nz92CqD+wlWhq5D+dKdaGy7BUr5QwaHg9C2",
"integrity": "sha384-nlzCq4Er6WPMedck7D5qAXa27wpbd75WI40/BlOhDA4ZKHgud1lhxfJWvy0bpFTA",
"elements": [
"research-map-plus-grid"
],
@ -991,7 +991,7 @@
"scriptUrl": "./research-map-plus-grid/research-map-plus-grid.js",
"embed": {
"iframe": "<iframe src=\"./research-map-plus-grid/research-map-plus-grid/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-map-plus-grid/research-map-plus-grid.js\" integrity=\"sha384-N12PTsk2HVN2Uh9nhF1R74uZ8+YO1nz92CqD+wlWhq5D+dKdaGy7BUr5QwaHg9C2\" crossorigin=\"anonymous\"></script>\n<research-map-plus-grid profile-config='{\"profile\":\"research-map-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-map-plus-grid>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-map-plus-grid/research-map-plus-grid.js\" integrity=\"sha384-nlzCq4Er6WPMedck7D5qAXa27wpbd75WI40/BlOhDA4ZKHgud1lhxfJWvy0bpFTA\" crossorigin=\"anonymous\"></script>\n<research-map-plus-grid profile-config='{\"profile\":\"research-map-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-map-plus-grid>"
},
"instances": [
{

File diff suppressed because one or more lines are too long

View file

@ -37,7 +37,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <research-map-plus-grid> custom element. -->
<script src="../../research-map-plus-grid.js" integrity="sha384-N12PTsk2HVN2Uh9nhF1R74uZ8+YO1nz92CqD+wlWhq5D+dKdaGy7BUr5QwaHg9C2" crossorigin="anonymous"></script>
<script src="../../research-map-plus-grid.js" integrity="sha384-nlzCq4Er6WPMedck7D5qAXa27wpbd75WI40/BlOhDA4ZKHgud1lhxfJWvy0bpFTA" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -37,7 +37,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <research-map-plus-grid> custom element. -->
<script src="../research-map-plus-grid.js" integrity="sha384-N12PTsk2HVN2Uh9nhF1R74uZ8+YO1nz92CqD+wlWhq5D+dKdaGy7BUr5QwaHg9C2" crossorigin="anonymous"></script>
<script src="../research-map-plus-grid.js" integrity="sha384-nlzCq4Er6WPMedck7D5qAXa27wpbd75WI40/BlOhDA4ZKHgud1lhxfJWvy0bpFTA" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order: