Prayer Progress carries its own "What can this map do?", so the ⓘ works wherever the map is embedded

On a partner page or a standalone preset page the ⓘ control rendered nothing, because only the
gallery answered it and the ⓘ's text lived in the gallery's settings. Now the map carries its info
(plugin-designs/doxa-simple-map/src/mapInfo.js) and a host only adds placement:

- MapInfoButton gains an opt-in `standalone` prop. When no host answers and the map carries info, it
  asks the map for a popup of its own (the 'standalone' event). If a real host appears later, the
  map's popup is dropped and the host takes over. Never inside the gallery (its panes carry
  data-doxa-gallery): there the gallery alone decides, its own info:false included.
- MapInfo gains `popupOnly` (with trigger 'control'): no floating button, since the map's control is
  the only button; it answers that control from inside the map, points at it once per page load,
  and opens the same popup (the bottom sheet on phones). It announces itself as local, so the
  control can tell it from a real host.
- Prayer Progress mounts that popup beside its control column, only when asked.

Per preset: the text describes the prayer map, so a map that shows the Prayer tab has info (the full
profile and the prayer preset); the engagement-only and adoption-only presets have none and show no
ⓘ, as before. A host's profile-config info:false removes the ⓘ. Every other MapInfoButton consumer
is unchanged (standalone is off by default).

doxa-simple-map grows by 20,590 bytes raw (5,699 gzipped), for compiling MapInfo. Rebuilt
doxa-simple-map and doxa-maps-spa, then tree + SRI.
This commit is contained in:
Doxa Maps 2026-09-30 06:15:11 +00:00
parent 1a26e4116c
commit d03b24e613
14 changed files with 228 additions and 72 deletions

View file

@ -81,6 +81,13 @@ const props = defineProps({
* actually on screen (see "control mode" below).
*/
trigger: { type: String, default: 'floating', validator: (v) => ['floating', 'control'].includes(v) },
/**
* With trigger 'control': the popup a MAP mounts for its own control when no host answers it (an
* embed, a standalone page). It never draws its own button, since the map's control is the only
* button; it answers that control from inside the map, points at it once per page load, and opens
* the same popup. It announces itself as local, so the control can tell it from a real host.
*/
popupOnly: { type: Boolean, default: false },
})
// ★ THE PAGE-LOAD POINTER (control mode). The pointer beside the map's own ⓘ shows ONCE PER PAGE LOAD:
// the first time that control is on screen in the load. It goes for the rest of the load once the reader
@ -292,7 +299,7 @@ onMounted(() => {
timer = window.setInterval(measureControl, 1500)
window.addEventListener('resize', onResize)
// A control that mounted before we did asked into the void; tell it to ask again.
try { window.dispatchEvent(new CustomEvent('dxmaps:mapinfo-host')) } catch { /* no CustomEvent */ }
try { window.dispatchEvent(new CustomEvent('dxmaps:mapinfo-host', { detail: { local: props.popupOnly } })) } catch { /* no CustomEvent */ }
})
onBeforeUnmount(() => {
if (pane) {
@ -305,7 +312,7 @@ onBeforeUnmount(() => {
window.removeEventListener('resize', onResize)
})
watch(open, (v) => { control.value?.setAttribute('aria-expanded', String(v)) })
const floatingShown = () => props.trigger !== 'control' || (!awaitingControl.value && !controlShown.value)
const floatingShown = () => !props.popupOnly && (props.trigger !== 'control' || (!awaitingControl.value && !controlShown.value))
// The pointer beside the control has been on screen: this page load has pointed once, so a remount (the
// gallery rebuilds a heavy tab on every switch back) does not point again. Marked on SCREEN, not on mount:
// a tab's MapInfo can mount inside a hidden pane.

View file

@ -27,8 +27,13 @@ import MapControlButton from './MapControlButton.vue'
const { t } = useI18n()
defineProps({
const props = defineProps({
isDark: { type: Boolean, default: false },
// The map carries its own info, so the control may stand ALONE: when no host answers (an embed on a
// partner page, a standalone preset page), it asks its map to mount a popup of its own (the
// 'standalone' event) instead of rendering nothing. Never inside the gallery: there the gallery alone
// decides, its own info:false included. Off by default, so every other consumer is unchanged.
standalone: { type: Boolean, default: false },
// 'round' (default) is the map-control form. 'rounded-square' is the dashboard HEADER form (the ⓘ
// sits in a header bar beside Share, not in a map's control column) — forwarded to MapControlButton.
shape: { type: String, default: 'round' },
@ -40,6 +45,7 @@ defineProps({
// QUESTION is asked from the toolbar's own element (provided by MapToolbar as mapToolbar.el), or from this
// component's placeholder's parent, and once answered the rendered button announces ITSELF, so the host
// measures and focuses the real element.
const emit = defineEmits(['standalone'])
const toolbar = inject('mapToolbar', null)
const self = getCurrentInstance()
const hosted = ref(false)
@ -51,12 +57,30 @@ function announce(from, el) {
try { from.dispatchEvent(new CustomEvent('dxmaps:mapinfo-control', { bubbles: true, composed: true, detail })) } catch { /* no CustomEvent */ }
return detail.ack === true
}
// Inside the gallery (its panes carry data-doxa-gallery), across shadow roots.
function inGallery(el) {
for (let n = el; n; n = n.parentNode || n.host) if (n.nodeType === 1 && n.hasAttribute('data-doxa-gallery')) return true
return false
}
// The map's own popup is up: it answers from the map, so this control is hosted by it.
let local = false
function ask() {
const from = origin()
if (!from) return
const was = hosted.value
hosted.value = announce(from, node())
if (hosted.value && !was) nextTick(() => { const el = node(); if (el) announce(el, el) })
// Nobody answered and the map carries its info: ask the map for its own popup. When it mounts, it
// announces itself ('dxmaps:mapinfo-host', detail.local), and the question above is asked again.
if (!hosted.value && props.standalone && !local && !inGallery(from)) { local = true; emit('standalone', true) }
}
// A host appeared. The map's own popup asks us again; any OTHER host (the gallery's) takes over, so the
// map's popup is dropped first: it sits inside the map and would answer before the gallery could.
function onHost(e) {
if (local && !(e && e.detail && e.detail.local)) {
local = false; hosted.value = false; emit('standalone', false); nextTick(ask); return
}
ask()
}
function openInfo() {
const el = node()
@ -65,9 +89,12 @@ function openInfo() {
}
onMounted(() => {
nextTick(ask)
window.addEventListener('dxmaps:mapinfo-host', ask)
window.addEventListener('dxmaps:mapinfo-host', onHost)
})
onBeforeUnmount(() => {
window.removeEventListener('dxmaps:mapinfo-host', onHost)
if (local) emit('standalone', false)
})
onBeforeUnmount(() => { window.removeEventListener('dxmaps:mapinfo-host', ask) })
</script>
<template>

View file

@ -54,6 +54,8 @@ import ShareButton from '@map/components/map-controls/ShareButton.vue'
// By path, not through map-controls/index.js: the barrel would pull the 'mapInfo' catalogue area into
// every bundle that imports a control.
import MapInfoButton from '@map/components/map-controls/MapInfoButton.vue'
import MapInfo from '@map/components/info/MapInfo.vue'
import { mapInfoFor } from './src/mapInfo.js'
// ─── Shadow DOM style injection ──────────────────────────────────────────────
useShadowStyles(`
@ -299,6 +301,12 @@ const showTabBar = computed(() => tabs.value.length > 1)
// ─── Tab state ────────────────────────────────────────────────────────────────
const activeTabId = ref(null)
const activeTab = computed(() => tabs.value.find(t => t.id === activeTabId.value) ?? tabs.value[0])
// ─── "What can this map do?" carried by the map ───────────────────────────────
// The map's own info (src/mapInfo.js, per preset). In the gallery the gallery answers the ⓘ control; on
// any other page the control asks for the map's own popup ('standalone'), mounted beside the toolbar.
// A host's profile-config info:false removes the ⓘ.
const ownInfo = computed(() => (profileConfig?.value?.info === false ? null : mapInfoFor(tabs.value)))
const infoLocal = ref(false)
// ─── Share embed path (ID→URL table owned by this profile) ────────────────────
// This is ONE parameterized profile rendering 3 maps chosen by tab id, so the
@ -1555,7 +1563,7 @@ onBeforeUnmount(() => {
which then hides its own floating button. It renders only where a MapInfo answers it, so a
standalone page (DX Life's home, the leaf) has no dead button. -->
<MapToolbar v-if="appReady" :has-geocoder="FEATURES.geocoder">
<MapInfoButton :is-dark="isDark" />
<MapInfoButton :is-dark="isDark" :standalone="!!ownInfo" @standalone="(on) => (infoLocal = on)" />
<ZoomInButton :map="map" :is-dark="isDark" />
<ZoomOutButton :map="map" :is-dark="isDark" />
<LocationButton :map="map" :is-dark="isDark" />
@ -1568,6 +1576,9 @@ onBeforeUnmount(() => {
<!-- "About this map" info button — feature-flagged off on this profile -->
<HelpButton v-if="FEATURES.infoButton" :is-dark="isDark" @open-help="showHelpPopup = true" />
</MapToolbar>
<!-- The map's own "What can this map do?" popup, only where no host answers its ⓘ control (an embed, a
standalone preset page). A sibling of the toolbar, so the control's announce reaches it. -->
<MapInfo v-if="infoLocal && ownInfo" trigger="control" popup-only v-bind="ownInfo" :locale="locale" />
<!-- Help popup modal -->
<div v-if="showHelpPopup" class="dsm-help-overlay" @click.self="showHelpPopup = false">

View file

@ -0,0 +1,19 @@
// What "What can this map do?" says about Prayer Progress. The map carries it, so the ⓘ works wherever the
// map is embedded; a host (the gallery) only adds placement. The keys are the library catalogue's
// ('mapInfo' area, all 11 locales).
//
// PER PRESET. The text describes the prayer map, so it belongs to a map that shows the PRAYER tab: the
// full profile (all three tabs, prayer first) and the prayer preset. The engagement and adoption presets
// show only their own tab and have no text of their own yet, so they have no info, and no ⓘ renders
// there: no wrong copy and no untranslated text.
const PRAYER = {
storageKey: 'prayer-map',
leadKey: 'mapInfo.tab.prayer-map.lead',
takeawayKey: 'mapInfo.tab.prayer-map.takeaway',
examples: [],
}
/** The map's info for the tabs it shows, or null when it has none. */
export function mapInfoFor(tabs) {
return (tabs || []).some((t) => t && t.id === 'prayer') ? PRAYER : null
}

File diff suppressed because one or more lines are too long

View file

@ -61,7 +61,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <doxa-maps-spa> custom element. -->
<script src="../../doxa-maps-spa.js" integrity="sha384-oYB02v1OWlb2erOc10jYt+QZEZl294usemur9EmNAorpr0TO+jqJq7b/C9wPK90X" crossorigin="anonymous"></script>
<script src="../../doxa-maps-spa.js" integrity="sha384-D/mRUs5xqO3YsM/jGut1prSjjF0SL4s9F3T83e2REfmYMaeW5j4J2oLgt8HE/vfS" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -61,7 +61,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <doxa-maps-spa> custom element. -->
<script src="../doxa-maps-spa.js" integrity="sha384-oYB02v1OWlb2erOc10jYt+QZEZl294usemur9EmNAorpr0TO+jqJq7b/C9wPK90X" crossorigin="anonymous"></script>
<script src="../doxa-maps-spa.js" integrity="sha384-D/mRUs5xqO3YsM/jGut1prSjjF0SL4s9F3T83e2REfmYMaeW5j4J2oLgt8HE/vfS" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -361,7 +361,7 @@
"bundle": "doxa-maps-spa",
"scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js",
"output": "dx-maps/doxa-maps-spa/doxa-maps-spa.js",
"integrity": "sha384-oYB02v1OWlb2erOc10jYt+QZEZl294usemur9EmNAorpr0TO+jqJq7b/C9wPK90X",
"integrity": "sha384-D/mRUs5xqO3YsM/jGut1prSjjF0SL4s9F3T83e2REfmYMaeW5j4J2oLgt8HE/vfS",
"elements": [
"doxa-maps-spa"
],
@ -389,7 +389,7 @@
"scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js",
"embed": {
"iframe": "<iframe src=\"./doxa-maps-spa/doxa-maps-spa/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=\"./doxa-maps-spa/doxa-maps-spa.js\" integrity=\"sha384-oYB02v1OWlb2erOc10jYt+QZEZl294usemur9EmNAorpr0TO+jqJq7b/C9wPK90X\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<doxa-maps-spa profile-config='{\"profile\":\"doxa-maps-spa\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-maps-spa>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-maps-spa/doxa-maps-spa.js\" integrity=\"sha384-D/mRUs5xqO3YsM/jGut1prSjjF0SL4s9F3T83e2REfmYMaeW5j4J2oLgt8HE/vfS\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<doxa-maps-spa profile-config='{\"profile\":\"doxa-maps-spa\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-maps-spa>"
},
"instances": [
{
@ -462,7 +462,7 @@
"bundle": "doxa-simple-map",
"scriptUrl": "./doxa-simple-map/doxa-simple-map.js",
"output": "dx-maps/doxa-simple-map/doxa-simple-map.js",
"integrity": "sha384-sK11c/bPtwhYTpqubigsRbjmjBRQ4SNz610WfvXg7Va5nA1vRHTdqeCFkREJKYVx",
"integrity": "sha384-r8dobCroLLbupF14pwXq+HL2uENl/hJppr/z74QTlpIDxOehrHYsL7M9321CsikD",
"elements": [
"doxa-map",
"doxa-simple-map"
@ -482,8 +482,8 @@
"scriptUrl": "./doxa-simple-map/doxa-simple-map.js",
"embed": {
"iframe": "<iframe src=\"./doxa-simple-map/doxa-simple-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-sK11c/bPtwhYTpqubigsRbjmjBRQ4SNz610WfvXg7Va5nA1vRHTdqeCFkREJKYVx\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-sK11c/bPtwhYTpqubigsRbjmjBRQ4SNz610WfvXg7Va5nA1vRHTdqeCFkREJKYVx\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>"
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-r8dobCroLLbupF14pwXq+HL2uENl/hJppr/z74QTlpIDxOehrHYsL7M9321CsikD\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-r8dobCroLLbupF14pwXq+HL2uENl/hJppr/z74QTlpIDxOehrHYsL7M9321CsikD\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>"
},
"instances": [
{

File diff suppressed because one or more lines are too long

View file

@ -70,7 +70,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <doxa-map> custom element. -->
<script src="../../doxa-simple-map.js" integrity="sha384-sK11c/bPtwhYTpqubigsRbjmjBRQ4SNz610WfvXg7Va5nA1vRHTdqeCFkREJKYVx" crossorigin="anonymous"></script>
<script src="../../doxa-simple-map.js" integrity="sha384-r8dobCroLLbupF14pwXq+HL2uENl/hJppr/z74QTlpIDxOehrHYsL7M9321CsikD" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -70,7 +70,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <doxa-map> custom element. -->
<script src="../../doxa-simple-map.js" integrity="sha384-sK11c/bPtwhYTpqubigsRbjmjBRQ4SNz610WfvXg7Va5nA1vRHTdqeCFkREJKYVx" crossorigin="anonymous"></script>
<script src="../../doxa-simple-map.js" integrity="sha384-r8dobCroLLbupF14pwXq+HL2uENl/hJppr/z74QTlpIDxOehrHYsL7M9321CsikD" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -70,7 +70,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <doxa-map> custom element. -->
<script src="../doxa-simple-map.js" integrity="sha384-sK11c/bPtwhYTpqubigsRbjmjBRQ4SNz610WfvXg7Va5nA1vRHTdqeCFkREJKYVx" crossorigin="anonymous"></script>
<script src="../doxa-simple-map.js" integrity="sha384-r8dobCroLLbupF14pwXq+HL2uENl/hJppr/z74QTlpIDxOehrHYsL7M9321CsikD" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -70,7 +70,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <doxa-map> custom element. -->
<script src="../../doxa-simple-map.js" integrity="sha384-sK11c/bPtwhYTpqubigsRbjmjBRQ4SNz610WfvXg7Va5nA1vRHTdqeCFkREJKYVx" crossorigin="anonymous"></script>
<script src="../../doxa-simple-map.js" integrity="sha384-r8dobCroLLbupF14pwXq+HL2uENl/hJppr/z74QTlpIDxOehrHYsL7M9321CsikD" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -361,7 +361,7 @@
"bundle": "doxa-maps-spa",
"scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js",
"output": "dx-maps/doxa-maps-spa/doxa-maps-spa.js",
"integrity": "sha384-oYB02v1OWlb2erOc10jYt+QZEZl294usemur9EmNAorpr0TO+jqJq7b/C9wPK90X",
"integrity": "sha384-D/mRUs5xqO3YsM/jGut1prSjjF0SL4s9F3T83e2REfmYMaeW5j4J2oLgt8HE/vfS",
"elements": [
"doxa-maps-spa"
],
@ -389,7 +389,7 @@
"scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js",
"embed": {
"iframe": "<iframe src=\"./doxa-maps-spa/doxa-maps-spa/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=\"./doxa-maps-spa/doxa-maps-spa.js\" integrity=\"sha384-oYB02v1OWlb2erOc10jYt+QZEZl294usemur9EmNAorpr0TO+jqJq7b/C9wPK90X\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<doxa-maps-spa profile-config='{\"profile\":\"doxa-maps-spa\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-maps-spa>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-maps-spa/doxa-maps-spa.js\" integrity=\"sha384-D/mRUs5xqO3YsM/jGut1prSjjF0SL4s9F3T83e2REfmYMaeW5j4J2oLgt8HE/vfS\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<doxa-maps-spa profile-config='{\"profile\":\"doxa-maps-spa\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-maps-spa>"
},
"instances": [
{
@ -462,7 +462,7 @@
"bundle": "doxa-simple-map",
"scriptUrl": "./doxa-simple-map/doxa-simple-map.js",
"output": "dx-maps/doxa-simple-map/doxa-simple-map.js",
"integrity": "sha384-sK11c/bPtwhYTpqubigsRbjmjBRQ4SNz610WfvXg7Va5nA1vRHTdqeCFkREJKYVx",
"integrity": "sha384-r8dobCroLLbupF14pwXq+HL2uENl/hJppr/z74QTlpIDxOehrHYsL7M9321CsikD",
"elements": [
"doxa-map",
"doxa-simple-map"
@ -482,8 +482,8 @@
"scriptUrl": "./doxa-simple-map/doxa-simple-map.js",
"embed": {
"iframe": "<iframe src=\"./doxa-simple-map/doxa-simple-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-sK11c/bPtwhYTpqubigsRbjmjBRQ4SNz610WfvXg7Va5nA1vRHTdqeCFkREJKYVx\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-sK11c/bPtwhYTpqubigsRbjmjBRQ4SNz610WfvXg7Va5nA1vRHTdqeCFkREJKYVx\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>"
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-r8dobCroLLbupF14pwXq+HL2uENl/hJppr/z74QTlpIDxOehrHYsL7M9321CsikD\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-r8dobCroLLbupF14pwXq+HL2uENl/hJppr/z74QTlpIDxOehrHYsL7M9321CsikD\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>"
},
"instances": [
{