From 32694e6d04201a4ccbebe7d0a9b9e587032ffeeb Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Sun, 27 Sep 2026 20:32:03 +0000 Subject: [PATCH] Update from source 9348d491 --- internal/backend-dev-plugin.mjs | 77 ++++++++++++++----- .../gospel-resources/resources-map.vue | 10 ++- .../plugin-studio/plugin-studio.vue | 20 ++++- plugin-designs/rudder-voice/rudder-voice.vue | 19 ++++- public/dx-maps/doxa-maps-spa/manifest.json | 20 ++--- .../gospel-resources/charts/index.html | 2 +- .../gospel-resources/data-tables/index.html | 2 +- .../gospel-dashboard/index.html | 2 +- .../gospel-resources/gospel-resources.js | 26 +++---- .../resources-list/index.html | 2 +- .../gospel-resources/resources-map/index.html | 2 +- public/dx-maps/index.html | 2 +- public/dx-maps/manifest.json | 20 ++--- public/dx-maps/plugin-studio/plugin-studio.js | 2 +- .../plugin-studio/plugin-studio/index.html | 2 +- .../plugin-studio/studio/index.html | 2 +- public/dx-maps/rudder-voice/rudder-voice.js | 18 ++--- .../rudder-voice/rudder-voice/index.html | 2 +- 18 files changed, 151 insertions(+), 79 deletions(-) diff --git a/internal/backend-dev-plugin.mjs b/internal/backend-dev-plugin.mjs index 5a7dd82c..9a81be79 100644 --- a/internal/backend-dev-plugin.mjs +++ b/internal/backend-dev-plugin.mjs @@ -7,6 +7,14 @@ * /api// routes, and stops it when the dev server stops. A backend that isn't built is skipped * with a hint: plugins without a backend never notice this file. * + * ★ ONE BACKEND PER `bun run dev`, SURVIVING VITE RESTARTS. Vite restarts itself whenever vite.config.js + * or anything it imports changes, and re-runs configureServer. Stopping the backend on every restart and + * starting a new one at once raced the old process for its port: the new one died with "address already + * in use" and Rudder showed "engine offline" until `bun run dev` was restarted by hand (measured + * 2026-09-27, twice in one session). Each backend now lives in a process-wide registry (globalThis — the + * config module itself is re-imported on a restart): a restart REUSES the running backend, it is stopped + * only when the dev process exits, and it is restarted (up to 5 times) if it crashes. + * * DEV ONLY (`apply: 'serve'`). A production build never starts or bundles a backend. */ import { spawn } from 'node:child_process' @@ -30,9 +38,40 @@ export function devBackendProxy() { return Object.fromEntries(DEV_BACKENDS.map((b) => [b.route, { target: `http://127.0.0.1:${b.port}`, changeOrigin: false }])) } +const REG = (globalThis.__dxDevBackends ||= { procs: new Map(), exitHooked: false, stopping: false }) +const isAlive = (name) => { const e = REG.procs.get(name); return !!e && e.child.exitCode === null && e.child.signalCode === null } + +function stopAll() { + REG.stopping = true + for (const { child } of REG.procs.values()) { try { child.kill('SIGTERM') } catch {} } +} + +function start(root, b, logger, restarts = 0) { + const tag = `[${b.name}]` + const child = spawn(resolve(root, b.bin), [], { cwd: root, env: { ...process.env, ...b.env }, stdio: ['ignore', 'pipe', 'pipe'] }) + const entry = { child, restarts, logger } + REG.procs.set(b.name, entry) + const out = (d) => String(d).trim().split('\n').forEach((l) => l && entry.logger.info(`${tag} ${l}`)) + child.stdout.on('data', out) + child.stderr.on('data', out) + child.on('exit', (code) => { + if (REG.procs.get(b.name) !== entry) return + REG.procs.delete(b.name) + if (REG.stopping) return + entry.logger.warn(`${tag} exited (${code})`) + // Crashed on its own: restart it, after its port has had a moment to free up. + if (entry.restarts < 5) { + setTimeout(() => { + if (REG.stopping || REG.procs.has(b.name)) return + entry.logger.warn(`${tag} restarting (${entry.restarts + 1}/5)`) + start(root, b, entry.logger, entry.restarts + 1) + }, 2000) + } + }) + logger.info(`${tag} started → ${b.route} on 127.0.0.1:${b.port}`) +} + export function backendDevPlugin(root) { - const children = [] - const alive = new Set() // backends whose process is running right now return { name: 'dx-backend-dev', apply: 'serve', @@ -44,7 +83,7 @@ export function backendDevPlugin(root) { // list. Registered here, so it runs before vite's proxy. for (const b of DEV_BACKENDS) { server.middlewares.use(b.route, (req, res, next) => { - if (alive.has(b.name)) return next() + if (isAlive(b.name)) return next() if ((req.url || '').startsWith('/events')) { res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' }) res.write(`data: ${JSON.stringify({ type: 'status', status: { engine: 'offline', error: 'The desktop engine is not running.' } })}\n\n`) @@ -54,27 +93,25 @@ export function backendDevPlugin(root) { res.end('[]') }) } + const logger = server.config.logger + if (!REG.exitHooked) { + REG.exitHooked = true + process.once('exit', stopAll) + process.once('SIGINT', () => { stopAll(); process.exit(0) }) + process.once('SIGTERM', () => { stopAll(); process.exit(0) }) + } for (const b of DEV_BACKENDS) { - const bin = resolve(root, b.bin) - if (!existsSync(bin)) { - server.config.logger.warn(`[backend] ${b.name} not built — its plugin will show "engine offline". Build: ${b.build}`) + if (isAlive(b.name)) { + REG.procs.get(b.name).logger = logger // log through the restarted server + logger.info(`[${b.name}] still running → ${b.route} (kept across the dev-server restart)`) continue } - const child = spawn(bin, [], { cwd: root, env: { ...process.env, ...b.env }, stdio: ['ignore', 'pipe', 'pipe'] }) - const tag = `[${b.name}]` - const out = (d) => String(d).trim().split('\n').forEach((l) => l && server.config.logger.info(`${tag} ${l}`)) - child.stdout.on('data', out) - child.stderr.on('data', out) - child.on('exit', (code) => { alive.delete(b.name); server.config.logger.warn(`${tag} exited (${code})`) }) - children.push(child) - alive.add(b.name) - server.config.logger.info(`${tag} started → ${b.route} on 127.0.0.1:${b.port}`) + if (!existsSync(resolve(root, b.bin))) { + logger.warn(`[backend] ${b.name} not built — its plugin will show "engine offline". Build: ${b.build}`) + continue + } + start(root, b, logger) } - const stop = () => children.forEach((c) => { try { c.kill('SIGTERM') } catch {} }) - server.httpServer?.on('close', stop) - process.once('exit', stop) - process.once('SIGINT', () => { stop(); process.exit(0) }) - process.once('SIGTERM', () => { stop(); process.exit(0) }) }, } } diff --git a/plugin-designs/gospel-resources/resources-map.vue b/plugin-designs/gospel-resources/resources-map.vue index 75ebe1bf..ee43e64d 100644 --- a/plugin-designs/gospel-resources/resources-map.vue +++ b/plugin-designs/gospel-resources/resources-map.vue @@ -365,8 +365,14 @@ const cardShard = (slug) => { const sxScope = (sx) => { if (!sx) return '' const n = Number(sx.parts) || 0 - const name = n === 66 ? tOr('gospel.res.fullBible', 'full Bible') - : n === 27 ? tOr('gospel.res.newTestament', 'New Testament') + /* ⚠ THE WORDS ALREADY EXISTED, TRANSLATED, and I asked for new keys without looking. rega found + gospel.charts.newTestament and gospel.charts.fullBible in all 11 locales — used by the charts + leaf — while my gospel.res.* existed nowhere, so every locale including Arabic fell back to my + English defaults, and even en read "full Bible" against the catalogue's "Full Bible". Two keys + for one word is the drift I keep fixing in other people's code; these are the same words, so + they are the same keys. Only the part count needed a new one. */ + const name = n === 66 ? t('gospel.charts.fullBible') + : n === 27 ? t('gospel.charts.newTestament') : n ? tOr('gospel.res.nParts', '{n} parts', { n: fmt(n) }) : '' return name ? `${name} — ${sx.src}` : sx.src diff --git a/plugin-designs/plugin-studio/plugin-studio.vue b/plugin-designs/plugin-studio/plugin-studio.vue index c8443de8..2bbcc353 100644 --- a/plugin-designs/plugin-studio/plugin-studio.vue +++ b/plugin-designs/plugin-studio/plugin-studio.vue @@ -1073,7 +1073,7 @@ export default defineComponent({ const h = document.createElement('div') h.setAttribute('data-studio-widgets', corner) const [v, x] = corner.split('-') - h.style.cssText = `position:fixed;${v}:12px;${x}:12px;z-index:2147483647;display:flex;flex-direction:column;align-items:${x === 'right' ? 'flex-end' : 'flex-start'};gap:8px;` + h.style.cssText = `position:fixed;${v}:max(12px,env(safe-area-inset-${v}));${x}:max(12px,env(safe-area-inset-${x}));z-index:2147483647;display:flex;flex-direction:column;align-items:${x === 'right' ? 'flex-end' : 'flex-start'};gap:8px;` document.body.appendChild(h) W.hosts[corner] = h return h @@ -1089,7 +1089,7 @@ export default defineComponent({ box.style.cssText = 'display:flex;flex-direction:column;align-items:inherit;gap:6px;' const panel = document.createElement('div') panel.setAttribute('data-widget-panel', '') - panel.style.cssText = 'display:none;width:min(380px,calc(100vw - 24px));height:min(520px,calc(100vh - 80px));position:relative;background:#fff;border-radius:10px;box-shadow:0 8px 30px rgba(0,0,0,.25);overflow:hidden;' + panel.style.cssText = 'display:none;width:min(380px,calc(100vw - 24px));height:min(520px,calc(100vh - 80px));height:min(520px,calc(100dvh - 80px - env(safe-area-inset-top) - env(safe-area-inset-bottom)));position:relative;background:#fff;border-radius:10px;box-shadow:0 8px 30px rgba(0,0,0,.25);overflow:hidden;' const btn = document.createElement('button') btn.type = 'button' // A catalogue label per widget ("widget:"), not the row key (rega / repo: the button read @@ -1124,7 +1124,21 @@ export default defineComponent({ const el = document.createElement(row.tag) el.setAttribute('profile-config', JSON.stringify(this.paneConfig(row, this.locale))) if (this.base) el.setAttribute('tree-base', this.base.replace(/\/+$/, '')) - el.style.cssText = 'display:block;position:absolute;inset:0;width:100%;height:100%;' + // The panel is a fixed size; on a phone the widget's content is taller than it, so the element scrolls + // inside the panel rather than being clipped by it. + el.style.cssText = 'display:block;position:absolute;inset:0;width:100%;height:100%;overflow-y:auto;overscroll-behavior:contain;' + // LIVE MIC, VISIBLE WHEN COLLAPSED: a widget that emits `recording` (Rudder does) turns its corner + // button red with a dot while it listens, so closing the panel never hides that the mic is on. + el.addEventListener('recording', (e) => { + const on = !!(Array.isArray(e.detail) ? e.detail[0] : e.detail) + const b = box.querySelector(':scope > button') + if (!b) return + if (!b.dataset.label) b.dataset.label = b.textContent + b.textContent = on ? '● ' + b.dataset.label : b.dataset.label + b.style.background = on ? '#7f1d1d' : '#0d1117' + b.style.borderColor = on ? '#ef4444' : '#30363d' + b.setAttribute('data-listening', on ? 'true' : 'false') + }) W.els[row.key] = el panel.appendChild(el) }).catch((e) => { panel.textContent = (e && e.message) || String(e) }) diff --git a/plugin-designs/rudder-voice/rudder-voice.vue b/plugin-designs/rudder-voice/rudder-voice.vue index 1038eba9..8bd1b527 100644 --- a/plugin-designs/rudder-voice/rudder-voice.vue +++ b/plugin-designs/rudder-voice/rudder-voice.vue @@ -12,11 +12,14 @@ * Everything is agent-interfaceable (the old Rudder's prime directive): the 🐞 panel copies the * engine log + status with a header telling an agent what to do with it. */ -import { computed, onBeforeUnmount, onMounted, ref, nextTick } from 'vue' +import { computed, onBeforeUnmount, onMounted, ref, nextTick, watch } from 'vue' defineOptions({ inheritAttrs: false }) const props = defineProps({ profileConfig: { type: String, default: '' } }) +// `recording` (true/false) tells a host that Rudder started or stopped listening — the Plugin Studio's +// corner button turns red with it, so a collapsed corner still shows the mic is live. +const emit = defineEmits(['recording']) const cfg = computed(() => { try { return props.profileConfig ? JSON.parse(props.profileConfig) : {} } catch { return {} } @@ -449,6 +452,8 @@ onBeforeUnmount(() => { window.removeEventListener('keydown', onKey) }) +watch(recording, (v) => emit('recording', v)) + const statusText = computed(() => ({ connecting: 'Connecting…', starting: 'Loading speech model… (about 20 s the first time)', @@ -585,7 +590,7 @@ const statusText = computed(() => ({ .rudder { --bg: #0b0f14; --panel: #111823; --line: #1f2937; --text: #e5e7eb; --muted: #9ca3af; --accent: #38bdf8; --rec: #ef4444; --ok: #22c55e; --warn: #f59e0b; - box-sizing: border-box; display: flex; flex-direction: column; gap: 14px; min-height: 480px; height: 100%; + box-sizing: border-box; display: flex; flex-direction: column; gap: 14px; min-height: max(100%, 480px); padding: 18px; background: var(--bg); color: var(--text); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; font-size: 15px; } @@ -653,4 +658,14 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 1 .debug dl { display: grid; grid-template-columns: 90px 1fr; gap: 6px 10px; margin: 0 0 10px; } .debug dt { color: var(--muted); } .debug dd { margin: 0; overflow-wrap: anywhere; } +/* A phone-sized panel: less padding, and a shorter draft so it stays in view below the controls. */ +@media (max-width: 480px) { + .rudder { min-height: 100%; padding: 12px; gap: 10px; } + .compose { min-height: 200px; } + .draft { min-height: 180px; } + /* Notices (engine offline, mic muted, …) sit below the draft here, so the draft stays in view. */ + .notice, .hint { order: 1; } + .bottom { order: 2; } + .debug { order: 3; } +} diff --git a/public/dx-maps/doxa-maps-spa/manifest.json b/public/dx-maps/doxa-maps-spa/manifest.json index 5dc6dce4..5ef3515f 100644 --- a/public/dx-maps/doxa-maps-spa/manifest.json +++ b/public/dx-maps/doxa-maps-spa/manifest.json @@ -723,7 +723,7 @@ "bundle": "gospel-resources", "scriptUrl": "./gospel-resources/gospel-resources.js", "output": "dx-maps/gospel-resources/gospel-resources.js", - "integrity": "sha384-4vTYBz9CWcW4INkXPQ65rGv/si06Nqs6pfZ5W6BefzaMsSEGU7UJOUAHWYHt8Kl5", + "integrity": "sha384-YTtLUyewI45Vkl3zYJG3cbCdkmo0WeCYZOWNSwF+2Ho7bA9UoxUzpVM22AV0ebTJ", "elements": [ "gospel-resources-map" ], @@ -745,7 +745,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" } }, { @@ -760,7 +760,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" } }, { @@ -775,7 +775,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n\n\n" + "script": "\n\n\n\n" } }, { @@ -790,7 +790,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" } }, { @@ -805,7 +805,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n\n\n" + "script": "\n\n\n\n" } } ] @@ -938,7 +938,7 @@ "bundle": "plugin-studio", "scriptUrl": "./plugin-studio/plugin-studio.js", "output": "dx-maps/plugin-studio/plugin-studio.js", - "integrity": "sha384-kMfLBZoyoNeBFEHEhmIVfueffC02EyscRAapROvxTG0Xhu5cGFRnDsCsaI5XmqyT", + "integrity": "sha384-ZJxq+M/pz1pOuZC6GxyGkrI4ngDWNQ31VirCuC3qnJobBzrctQzdcP7DzllrqqJF", "elements": [ "plugin-studio" ], @@ -968,7 +968,7 @@ "scriptUrl": "./plugin-studio/plugin-studio.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" }, "instances": [ { @@ -1185,7 +1185,7 @@ "bundle": "rudder-voice", "scriptUrl": "./rudder-voice/rudder-voice.js", "output": "dx-maps/rudder-voice/rudder-voice.js", - "integrity": "sha384-Pb1pQJqoB3wMTum8vw0uUrm7e74j90ytj1hNdIl/1HbRlfy1YoT0hf6ggWQ3qDNO", + "integrity": "sha384-k35f+7ZzzkEl0s5QiO+EB8OksRe1MBgN2MSqPEw/AYNkencojRBIOV8hhIiyYI2z", "elements": [ "rudder-voice" ], @@ -1206,7 +1206,7 @@ "scriptUrl": "./rudder-voice/rudder-voice.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" } } ] diff --git a/public/dx-maps/gospel-resources/charts/index.html b/public/dx-maps/gospel-resources/charts/index.html index 19c772a3..07f5ce79 100644 --- a/public/dx-maps/gospel-resources/charts/index.html +++ b/public/dx-maps/gospel-resources/charts/index.html @@ -32,7 +32,7 @@ - + - + - + - + - + + diff --git a/public/dx-maps/manifest.json b/public/dx-maps/manifest.json index 5dc6dce4..5ef3515f 100644 --- a/public/dx-maps/manifest.json +++ b/public/dx-maps/manifest.json @@ -723,7 +723,7 @@ "bundle": "gospel-resources", "scriptUrl": "./gospel-resources/gospel-resources.js", "output": "dx-maps/gospel-resources/gospel-resources.js", - "integrity": "sha384-4vTYBz9CWcW4INkXPQ65rGv/si06Nqs6pfZ5W6BefzaMsSEGU7UJOUAHWYHt8Kl5", + "integrity": "sha384-YTtLUyewI45Vkl3zYJG3cbCdkmo0WeCYZOWNSwF+2Ho7bA9UoxUzpVM22AV0ebTJ", "elements": [ "gospel-resources-map" ], @@ -745,7 +745,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" } }, { @@ -760,7 +760,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" } }, { @@ -775,7 +775,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n\n\n" + "script": "\n\n\n\n" } }, { @@ -790,7 +790,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" } }, { @@ -805,7 +805,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n\n\n" + "script": "\n\n\n\n" } } ] @@ -938,7 +938,7 @@ "bundle": "plugin-studio", "scriptUrl": "./plugin-studio/plugin-studio.js", "output": "dx-maps/plugin-studio/plugin-studio.js", - "integrity": "sha384-kMfLBZoyoNeBFEHEhmIVfueffC02EyscRAapROvxTG0Xhu5cGFRnDsCsaI5XmqyT", + "integrity": "sha384-ZJxq+M/pz1pOuZC6GxyGkrI4ngDWNQ31VirCuC3qnJobBzrctQzdcP7DzllrqqJF", "elements": [ "plugin-studio" ], @@ -968,7 +968,7 @@ "scriptUrl": "./plugin-studio/plugin-studio.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" }, "instances": [ { @@ -1185,7 +1185,7 @@ "bundle": "rudder-voice", "scriptUrl": "./rudder-voice/rudder-voice.js", "output": "dx-maps/rudder-voice/rudder-voice.js", - "integrity": "sha384-Pb1pQJqoB3wMTum8vw0uUrm7e74j90ytj1hNdIl/1HbRlfy1YoT0hf6ggWQ3qDNO", + "integrity": "sha384-k35f+7ZzzkEl0s5QiO+EB8OksRe1MBgN2MSqPEw/AYNkencojRBIOV8hhIiyYI2z", "elements": [ "rudder-voice" ], @@ -1206,7 +1206,7 @@ "scriptUrl": "./rudder-voice/rudder-voice.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" } } ] diff --git a/public/dx-maps/plugin-studio/plugin-studio.js b/public/dx-maps/plugin-studio/plugin-studio.js index 23968628..eb985135 100644 --- a/public/dx-maps/plugin-studio/plugin-studio.js +++ b/public/dx-maps/plugin-studio/plugin-studio.js @@ -382,4 +382,4 @@ .ps-hint { position:absolute; inset:0; display:grid; place-items:center; text-align:center; color:#6d766e; font-size:13px; padding:20px; } .ps-hint.err { color:#f87171; } .ps-hint small { color:#6d766e; } -`,Pp={5:"App shell · nested-mfe-spa",4:"Composite element",3:"Multi-view element",2:"Preset element",1:"Single element"},Vi={"nested-mfe-spa":0,"nested-elements-mfe":1,monolithic:2,parameterized:3,single:4},Tp=e=>Vi[e]!=null?5-Vi[e]:1,Cp={5:"nested-mfe-spa",4:"nested-elements-mfe",3:"monolithic",2:"parameterized",1:"single"},Hn={5:"monitor",4:"tree",3:"layers",2:"grid",1:"embed"},Ki=new Set(["doxa-research-map","doxa-simple-map","cities-internet-map","gospel-resources-map","my-upg-100-list-map","doxa-map","doxa-maps-spa","dashboard-plus-grid","research-dashboard-map","demo-map","all-people-groups","country-posters-map","key-cities-map","research-map-plus-grid","gospel-internet-board"]),qi=new Set(["big-picture"]),Ho={};for(const[e,t]of Object.entries(Object.assign({"../../library/i18n/locales/ar/studio.json":Er,"../../library/i18n/locales/de/studio.json":Pr,"../../library/i18n/locales/en/studio.json":Tr,"../../library/i18n/locales/es/studio.json":Cr,"../../library/i18n/locales/fr/studio.json":Mr,"../../library/i18n/locales/hi/studio.json":Ar,"../../library/i18n/locales/it/studio.json":Or,"../../library/i18n/locales/pt/studio.json":Ir,"../../library/i18n/locales/ro/studio.json":Hr,"../../library/i18n/locales/ru/studio.json":Fr,"../../library/i18n/locales/zh/studio.json":Rr}))){const o=e.match(/locales\/([^/]+)\/studio\.json$/);o&&(Ho[o[1]]=t)}const Mp={"doxa-maps-spa/doxa-maps-spa":"Research Gallery"},Vt={};function Gi(e,t){return Vt[e]||(Vt[e]=new Promise((o,n)=>{const s=document.createElement("script");s.src=e,(/^\/plugin-designs\//.test(e)||/\/index\.js(\?|$)/.test(e))&&(s.type="module"),s.onload=()=>o(),s.onerror=()=>{delete Vt[e],n(new Error("failed to load "+e))},document.head.appendChild(s)})),Vt[e]}function Yi(e,t){return typeof customElements>"u"||customElements.get(e)?Promise.resolve():Promise.race([customElements.whenDefined(e),new Promise((o,n)=>setTimeout(()=>{customElements.get(e)||n(new Error("<"+e+"> never registered (bundle loaded but defined no element)"))},15e3))])}const Ap=$o({name:"PluginStudio",inheritAttrs:!1,components:{VerticalTabsLayout:zc,StudioTree:kp},props:{treeBase:{type:String,default:""},profileConfig:{type:[String,Object],default:""},provider:{type:String,default:""},heading:{type:String,default:""},tokenUrl:{type:String,default:""},tk:{type:String,default:""}},setup(){return Mn(Ep,"plugin-studio"),{injectedBase:Tt("psTreeBase","")}},data(){return{activeKey:"",embedOpen:!1,locale:this.initialLocale(),localeOpen:!1,settingsOpen:!1,headerHidden:mt(ji)==="1",engineOpen:!1,userProvider:mt(Bi),tokenBusy:!1,tokenErr:"",tokenDraft:mt(Oo),urlDraft:mt(Io),userTk:mt(Oo),userTokenUrl:mt(Io),fetchedTk:"",bakedTk:"",hostProvider:"",switcherLangs:Mo,rows:[],manifestBundles:[]}},computed:{cfg(){let e=this.profileConfig;if(typeof e=="string")try{e=e?JSON.parse(e):{}}catch{e={}}return e&&typeof e=="object"?e:{}},base(){const e=(this.treeBase||this.cfg.treeBase||this.injectedBase||"").trim();return e?e.replace(/\/+$/,"")+"/":""},flatRows(){return this.rows},groups(){const e={};for(const t of this.rows)(e[t.cap]=e[t.cap]||[]).push(t);return[5,4,3,2,1].filter(t=>e[t]&&e[t].length).map(t=>({cap:t,label:Pp[t]||"capability "+t,rows:e[t]}))},treeSections(){const e=new Map(this.compositionTrees.map(a=>[a.nodes[0].selects,a])),t=new Map;for(const a of this.rows)t.has(a.bundle)||t.set(a.bundle,[]),t.get(a.bundle).push(a);const o=[...t.entries()].map(([a,l])=>({bundle:a,rows:l,cap:Math.max(...l.map(r=>r.cap)),stage:l[0].stage})),n=o.filter(a=>a.stage!=="production").sort((a,l)=>l.cap-a.cap||a.bundle.localeCompare(l.bundle)),s=o.filter(a=>a.stage==="production"),i=[5,4,3,2,1].map(a=>({cap:a,group:s.filter(l=>l.cap===a).sort((l,r)=>l.bundle.localeCompare(r.bundle))}));return i.push({cap:"experimental",group:n}),i.map(({cap:a,group:l})=>{if(!l.length)return null;const r=[],u=(p,h,v)=>{const y=e.get(p.key);if(r.push({id:p.key,parent:v,depth:h,label:p.label,desc:p.tag,icon:p.icon,target:p.key,canonical:!0,kids:y?y.nodes[0].kids:0,title:p.label+" · <"+p.tag+"> · CAP "+p.cap+" "+this.tr("cap"+p.cap)}),!y)return;const H=L=>L===0?p.key:p.key+">"+L;for(const L of y.nodes.slice(1))r.push({id:H(L.id),parent:H(L.ancestors[L.ancestors.length-1]),depth:h+L.depth,label:L.label,part:!!L.part,target:L.selects||"",canonical:!1,icon:L.part?"dots":Hn[L.cap]||"embed",desc:L.part?this.tr("noStandalone"):"cap "+L.cap+" · "+L.tag,kids:L.kids||0,title:L.part?L.label+" · "+this.tr("partOf",{name:p.label}):L.label+" · <"+L.tag+"> · CAP "+L.cap+" "+this.tr("cap"+L.cap)})};for(const p of l){const h=[...p.rows].sort((y,H)=>H.cap-y.cap||y.label.localeCompare(H.label));if(h.length===1){u(h[0],0,"");continue}const v="bundle:"+p.bundle;r.push({id:v,parent:"",depth:0,label:p.bundle,desc:this.tr("elementsCount",{n:h.length}),icon:"folder",target:h[0].key,canonical:!1,folder:!0,kids:h.length,title:p.bundle+" · plugin-designs/"+p.bundle+"/ · "+h.length+" "+this.tr("elements")});for(const y of h)u(y,1,v)}return a==="experimental"?{id:"stage-experimental",cap:0,label:this.tr("stageExperimental"),title:this.tr("stageExperimental"),icon:"layers",nodes:r}:{id:"cap-"+a,cap:a,label:this.tr("cap"+a),title:this.tr("cap"+a)+" · "+(Cp[a]||""),icon:Hn[a]||"embed",nodes:r}}).filter(Boolean)},compositionTrees(){const e=[],t=(o,n,s,i,a)=>{const l=this.manifestBundles.find(v=>v.bundle===o.bundle),r=o.cap>=4&&l&&l.composes||[],u=[],p=[],h=new Set;for(const v of r){const y=this.resolveRef(v,o.bundle);if(!y){p.push(v);continue}y.key===o.key||h.has(y.key)||(h.add(y.key),u.push(y))}u.sort((v,y)=>y.cap-v.cap||v.label.localeCompare(y.label));for(const v of u){const y={id:i.length,label:v.label,tag:v.tag,cap:v.cap,selects:v.key,depth:n+1,ancestors:a,kids:0};i.push(y);const H=i.length;s.has(v.key)||t(v,n+1,new Set([...s,v.key]),i,[...a,y.id]),y.kids=i.filter((L,ee)=>ee>=H&&L.depth===n+2).length}for(const v of p)i.push({id:i.length,label:v,part:!0,selects:o.key,depth:n+1,ancestors:a,kids:0})};for(const o of this.manifestBundles){if(!o.composes||!o.composes.length||qi.has(o.bundle))continue;const n=this.rows.find(i=>i.bundle===o.bundle);if(!n)continue;const s=[{id:0,label:n.label,tag:n.tag,cap:n.cap,selects:n.key,depth:0,ancestors:[]}];t(n,0,new Set([n.key]),s,[0]),s[0].kids=s.filter(i=>i.depth===1).length,s.length>1&&e.push({bundle:o.bundle,nodes:s})}return e},active(){return this.rows.find(e=>e.key===this.activeKey)||null},effectiveTk(){return this.userTk||this.fetchedTk||this.tk||this.cfg.tk||this.bakedTk||""},effectiveProvider(){const e=String(this.userProvider||this.provider||this.cfg.provider||"").toLowerCase().trim();return e==="maplibre"||e==="mapbox"?e:""},engines(){return[{id:"",label:this.tr("engineDefault"),note:""},{id:"mapbox",label:"Mapbox",note:this.tr("engineMapboxNote")},{id:"maplibre",label:"MapLibre",note:this.tr("engineMaplibreNote")}]},engineLabel(){return this.userProvider==="mapbox"?"Mapbox":this.userProvider==="maplibre"?"MapLibre":this.tr("engineDefault")},tokenSource(){return this.userTk?"yours":this.fetchedTk?"url":this.tk||this.cfg.tk||this.bakedTk?"built":"none"},tokenStatus(){return this.effectiveProvider==="maplibre"?this.tr("tokenNotNeeded"):this.tokenSource==="yours"?this.tr("tokenSourceYours"):this.tokenSource==="url"?this.tr("tokenSourceUrl",{url:this.userTokenUrl}):this.tokenSource==="built"?this.tr("tokenSourceBuilt"):this.tr("tokenSourceNone")},countLabel(){const e=new Set(this.rows.map(t=>t.bundle)).size;return this.tr("countLabel",{bundles:e,elements:this.rows.length})},activeLang(){return yp(this.locale)||{code:this.locale,flag:"🌐",nativeName:this.locale}},uiDir(){return(this.activeLang&&this.activeLang.dir)==="rtl"?"rtl":"ltr"}},mounted(){this.bakedTk=typeof window<"u"&&window.MAP_TOKEN||"",this.hostProvider=typeof window<"u"&&typeof window.MAP_PROVIDER=="string"?window.MAP_PROVIDER:"",this.publishProvider(),this.userTk?this.publishToken():(this.userTokenUrl||this.tokenUrl||this.cfg.tokenUrl)&&this.fetchToken(this.userTokenUrl||this.tokenUrl||this.cfg.tokenUrl).then(e=>{e&&e!==this.fetchedTk&&(this.fetchedTk=e,this.publishToken(),this.remountPanes())}).catch(()=>{}),this.loadManifest()},methods:{async fetchToken(e){if(!/^https?:\/\//i.test(e))throw new Error("not an http(s) URL");let t;try{t=await fetch(e,{cache:"no-store",credentials:"same-origin"})}catch{throw new Error("the request was blocked or the server did not answer (cross-origin rules can do this)")}if(!t.ok)throw new Error("HTTP "+t.status);const o=(await t.text()).trim();let n=o;try{const s=JSON.parse(o);n=s&&(s.token||s.tk||s.accessToken)||(typeof s=="string"?s:"")}catch{}if(n=String(n||"").trim(),n.startsWith("sk."))throw new Error(this.tr("tokenSecret"));if(!n.startsWith("pk."))throw new Error(this.tr("tokenNotPk"));return n},async applyToken(){this.tokenErr="";const e=this.tokenDraft,t=this.urlDraft;if(e.startsWith("sk.")){this.tokenErr=this.tr("tokenSecret");return}if(e&&!e.startsWith("pk.")){this.tokenErr=this.tr("tokenNotPk");return}this.tokenBusy=!0;try{let o="";if(!e&&t)try{o=await this.fetchToken(t)}catch(n){this.tokenErr=this.tr("tokenUrlFailed",{why:n.message});return}this.userTk=e,this.userTokenUrl=e?"":t,this.fetchedTk=o,_t(Oo,this.userTk),_t(Io,this.userTokenUrl),this.publishToken(),this.remountPanes(),this.settingsOpen=!1}finally{this.tokenBusy=!1}},setHeaderHidden(e){this.headerHidden=!!e,this.settingsOpen=!1,this.engineOpen=!1,this.localeOpen=!1,_t(ji,e?"1":"")},setProvider(e){this.engineOpen=!1,e!==this.userProvider&&(this.userProvider=e,_t(Bi,e),this.publishProvider(),this.remountPanes())},publishProvider(){typeof window>"u"||(this.effectiveProvider?window.MAP_PROVIDER=this.effectiveProvider:this.hostProvider?window.MAP_PROVIDER=this.hostProvider:"MAP_PROVIDER"in window&&delete window.MAP_PROVIDER)},clearToken(){this.tokenDraft="",this.urlDraft="",this.tokenErr="",this.userTk="",this.userTokenUrl="",this.fetchedTk="",_t(Oo,""),_t(Io,""),this.publishToken(),this.remountPanes()},publishToken(){typeof window>"u"||(this.effectiveTk?(Wi(this.effectiveTk),window.MAP_TOKEN!==this.effectiveTk&&(window.MAP_TOKEN=this.effectiveTk)):Lp())},remountPanes(){for(const t of this.rows)t.mounted&&this.releaseRow(t);const e=this.active;e&&this.$nextTick(()=>{this.activeKey===e.key&&this.mountElement(e)})},tr(e,t){const o=(this.locale||"en").split("-")[0];let n=(Ho[this.locale]||{})[e]||(Ho[o]||{})[e]||(Ho.en||{})[e]||e;if(t)for(const s in t)n=n.split("{"+s+"}").join(String(t[s]));return n},resolveRef(e,t){return t&&this.rows.find(o=>o.key===t+"/"+e)||this.rows.find(o=>o.key===e)||this.rows.find(o=>o.tag===e)||this.rows.find(o=>o.bundle===e)||null},setSlot(e,t){t&&(this._slots=Object.assign(this._slots||{},{[e]:t}))},initialLocale(){let e=this.profileConfig;if(typeof e=="string")try{e=e?JSON.parse(e):{}}catch{e={}}let t="";try{const n=new URLSearchParams(window.location.search);t=n.get("lang")||n.get("locale")||""}catch{}const o=e&&(e.locale||e.lang)||t;return o?In(o):wp()},paneConfig(e,t){const o={profile:e.profile,instanceId:"ps-"+e.key.replace(/\//g,"-"),locale:t};this.effectiveTk&&(o.tk=this.effectiveTk);const n=this.userTokenUrl||this.tokenUrl||this.cfg.tokenUrl;return n&&(o.tokenUrl=n),this.effectiveProvider&&(o.provider=this.effectiveProvider),this.base&&(o.treeBase=this.base),o},setLocale(e){this.locale=e,this.localeOpen=!1,Sp(e);try{for(const t of this.rows){if(!t.mounted)continue;const o=this._slots&&this._slots[t.key],n=o&&o.firstElementChild;n&&n.setAttribute&&n.setAttribute("profile-config",JSON.stringify(this.paneConfig(t,e)))}}catch{}},resolve(e){const t=String(e);if(/^(https?:)?\/\//.test(t)||t.startsWith("/"))return t;const o=t.replace(/^\.\//,"");return this.base?this.base.replace(/\/+$/,"")+"/"+o:"../"+o},loadManifest(){const e=o=>{this.manifestBundles=o&&o.bundles||[],this.rows=this.rowsFromManifest(o),this.setupWidgets(),this.route()},t=typeof window<"u"&&window.__psBaked||null;if(typeof fetch=="function"&&typeof location<"u"&&location.protocol!=="file:"){const o=this.base?this.resolve("manifest.json"):"../manifest.json";fetch(o,{cache:"no-cache"}).then(n=>n.ok?n.json():null).then(n=>e(n||t||{bundles:[]})).catch(()=>e(t||{bundles:[]}))}else e(t||{bundles:[]})},rowsFromManifest(e){const t=[];for(const o of e.bundles||[])if(!(o.bundle==="plugin-studio"||qi.has(o.bundle)))for(const n of o.profiles||[]){const s=o.elements&&o.elements.length?o.elements:null,i=(n.element&&(!s||s.includes(n.element))?n.element:null)||s&&s[0]||n.element||o.bundle,a=Tp(n.type||"single"),l=Ki.has(i)||Ki.has(o.bundle)||n.heavy===!0;t.push({key:o.bundle+"/"+n.profile,bundle:o.bundle,stage:o.stage==="production"?"production":"experimental",label:Mp[o.bundle+"/"+n.profile]||n.profile,profile:n.profile,tag:i,cap:a,icon:Hn[a]||"embed",description:n.description||"",widget:n.widget&&["bottom-right","bottom-left","top-right","top-left"].includes(n.widget.corner)?n.widget.corner:"",heavy:l,bundleJs:o.scriptUrl||o.bundle+"/"+o.bundle+".js",embed:n.embed&&n.embed.script||"",mounted:!1,state:"idle",error:""})}return t.sort((o,n)=>n.cap-o.cap||o.bundle.localeCompare(n.bundle)||o.label.localeCompare(n.label)),t},route(){const e=(typeof location<"u"&&location.hash||"").replace(/^#\/?/,"");if(e&&this.rows.some(o=>o.key===e)){this.select(e);return}const t=this.readLastTab();if(t&&this.rows.some(o=>o.key===t)){this.select(t);return}this.rows.length&&this.select(this.rows[0].key)},storageKey(){return"dx-studio-tab:"+(typeof location<"u"&&location.pathname||"")},readLastTab(){try{return window.localStorage.getItem(this.storageKey())||""}catch{return""}},writeLastTab(e){try{window.localStorage.setItem(this.storageKey(),e)}catch{}},select(e){if(!this.rows.some(s=>s.key===e))return;const t=this.rows.find(s=>s.key===e);if(t&&t.widget){this.openWidget(t,!0);return}const o=this.activeKey;if(this.activeKey=e,this.embedOpen=!1,o&&o!==e){const s=this.rows.find(i=>i.key===o);s&&s.heavy&&s.mounted&&this.releaseRow(s)}const n=this.rows.find(s=>s.key===e);n&&(this.writeLastTab(e),n.mounted||this.$nextTick(()=>{this.activeKey===n.key&&this.mountElement(n)}))},releaseRow(e){try{const t=this._slots&&this._slots[e.key];t&&(t.innerHTML="")}catch{}this._slots&&delete this._slots[e.key],e.mounted=!1,e.state="idle",e.error=""},widgetStore(){return window.__doxaStudioWidgets||(window.__doxaStudioWidgets={hosts:{},els:{}}),window.__doxaStudioWidgets},widgetHost(e){const t=this.widgetStore();if(t.hosts[e]&&t.hosts[e].isConnected)return t.hosts[e];const o=document.createElement("div");o.setAttribute("data-studio-widgets",e);const[n,s]=e.split("-");return o.style.cssText=`position:fixed;${n}:12px;${s}:12px;z-index:2147483647;display:flex;flex-direction:column;align-items:${s==="right"?"flex-end":"flex-start"};gap:8px;`,document.body.appendChild(o),t.hosts[e]=o,o},setupWidgets(){for(const e of this.rows.filter(t=>t.widget)){const t=this.widgetStore(),o=this.widgetHost(e.widget);let n=o.querySelector(`[data-widget="${e.key}"]`);if(!n){n=document.createElement("div"),n.setAttribute("data-widget",e.key),n.style.cssText="display:flex;flex-direction:column;align-items:inherit;gap:6px;";const i=document.createElement("div");i.setAttribute("data-widget-panel",""),i.style.cssText="display:none;width:min(380px,calc(100vw - 24px));height:min(520px,calc(100vh - 80px));position:relative;background:#fff;border-radius:10px;box-shadow:0 8px 30px rgba(0,0,0,.25);overflow:hidden;";const a=document.createElement("button");a.type="button";const l="widget:"+e.key,r=this.tr(l);a.textContent=r!==l?r:e.label,a.setAttribute("aria-expanded","false"),a.style.cssText="font:600 13px system-ui,sans-serif;padding:8px 14px;border-radius:999px;border:1px solid #30363d;background:#0d1117;color:#e6edf3;cursor:pointer;box-shadow:0 2px 10px rgba(0,0,0,.25);",a.addEventListener("click",()=>this.openWidget(e,i.style.display==="none")),n.appendChild(i),n.appendChild(a),o.appendChild(n)}t.els[e.key]&&!n.querySelector(e.tag)&&n.querySelector("[data-widget-panel]").appendChild(t.els[e.key]);let s=!1;try{s=localStorage.getItem("plugin-studio:widget-open:"+e.key)==="1"}catch{}s&&this.openWidget(e,!0)}},openWidget(e,t){const n=this.widgetHost(e.widget).querySelector(`[data-widget="${e.key}"]`);if(!n){this.setupWidgets();return}const s=n.querySelector("[data-widget-panel]"),i=n.querySelector("button");s.style.display=t?"block":"none",i.setAttribute("aria-expanded",t?"true":"false");try{localStorage.setItem("plugin-studio:widget-open:"+e.key,t?"1":"0")}catch{}const a=this.widgetStore();!t||a.els[e.key]||Gi(this.resolve(e.bundleJs)).then(()=>Yi(e.tag)).then(()=>{if(a.els[e.key])return;const l=document.createElement(e.tag);l.setAttribute("profile-config",JSON.stringify(this.paneConfig(e,this.locale))),this.base&&l.setAttribute("tree-base",this.base.replace(/\/+$/,"")),l.style.cssText="display:block;position:absolute;inset:0;width:100%;height:100%;",a.els[e.key]=l,s.appendChild(l)}).catch(l=>{s.textContent=l&&l.message||String(l)})},mountElement(e){e.mounted=!0,e.state="loading";const t=this.resolve(e.bundleJs);Gi(t).then(()=>Yi(e.tag)).then(()=>{try{if(e.heavy&&this.activeKey!==e.key){e.mounted=!1,e.state="idle";return}const o=this._slots&&this._slots[e.key];if(!o){e.state="error",e.error="no slot";return}o.innerHTML="";const n=document.createElement(e.tag);n.setAttribute("profile-config",JSON.stringify(this.paneConfig(e,this.locale))),this.base&&n.setAttribute("tree-base",this.base.replace(/\/+$/,"")),n.style.cssText="display:block;position:absolute;inset:0;width:100%;height:100%;",o.appendChild(n),e.state="ready"}catch(o){e.state="error",e.error="mount failed: "+(o&&o.message||String(o))}}).catch(o=>{e.state="error",e.error=o&&o.message||String(o)})},copyText(e,t){const o=()=>{const n=t.textContent;t.textContent=this.tr("copied"),setTimeout(()=>{t.textContent=n},1200)};if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(e).then(o,()=>{});else try{const n=document.createElement("textarea");n.value=e,document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n),o()}catch{}}}}),Op={class:"ps-count"},Ip={class:"ps-locale"},Hp=["aria-expanded","aria-label"],Fp={class:"ps-flag"},Rp={class:"ps-locale-name"},Dp={key:0,class:"ps-locale-menu",role:"listbox"},Up=["aria-selected"],Wp=["onClick"],zp={class:"ps-flag"},jp={class:"ps-locale-name"},Bp={class:"ps-locale-en"},Vp={class:"ps-locale ps-engine"},Kp=["aria-expanded","aria-label","title"],qp={class:"ps-locale-name"},Gp=["aria-label"],Yp=["aria-selected"],Xp=["onClick"],Jp={class:"ps-locale-name"},Zp={class:"ps-locale-en"},Qp={class:"ps-token"},ed=["aria-expanded","title"],td={class:"ps-locale-name"},od={class:"ps-token-head"},nd={class:"ps-token-label"},sd={class:"ps-token-label"},id={class:"ps-token-row"},ad=["disabled"],ld={class:"ps-token-note"},rd=["title","aria-label"],cd={class:"ps-locale-name"},pd={key:0,class:"ps-toolbar"},dd={class:"ps-bar"},ud={class:"ps-bar-t"},fd={class:"ps-bar-sub"},hd={key:0},gd=["aria-expanded"],bd={key:0,class:"ps-embed"},$d=["value"],md=["title","aria-label"],_d={class:"ps-stage"},vd=["hidden"],xd={key:0,class:"ps-hint"},kd={key:1,class:"ps-hint err"},yd={key:0,class:"ps-hint"};function wd(e,t,o,n,s,i){const a=Os("StudioTree"),l=Os("VerticalTabsLayout");return N(),yo(l,{title:e.heading||e.tr("title"),dir:e.uiDir,"nav-label":e.tr("navLabel"),labels:{toggleList:e.tr("toggleList"),openViews:e.tr("openViews"),expandList:e.tr("expandList"),collapseList:e.tr("collapseList"),collapse:e.tr("collapse")},header:!e.headerHidden,active:e.activeKey,"onUpdate:active":e.select},{rail:ut(({collapsed:r,expand:u,pick:p})=>[me(a,{sections:e.treeSections,active:e.activeKey,collapsed:r,expand:u,pick:p,strings:{filterPlaceholder:e.tr("filterPlaceholder"),collapseAll:e.tr("collapseAll"),noMatch:e.tr("noMatch"),treeLabel:e.tr("navLabel"),openSection:e.tr("openSection"),part:e.tr("part")}},null,8,["sections","active","collapsed","expand","pick","strings"])]),brand:ut(()=>[...t[11]||(t[11]=[_("span",{class:"ps-logo","aria-hidden":"true"},[_("svg",{viewBox:"0 0 24 24",width:"22",height:"22",fill:"none",stroke:"#92b195","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[_("path",{d:"M10 3v3M14 3v3M7 6h10v5a5 5 0 0 1-10 0V6Z"}),_("path",{d:"M12 16v5"})])],-1)])]),meta:ut(()=>[_("span",Op,P(e.countLabel),1),_("span",Ip,[_("button",{type:"button",class:"ps-locale-btn","aria-expanded":String(e.localeOpen),"aria-label":e.tr("changeLanguage"),onClick:t[0]||(t[0]=r=>{e.localeOpen=!e.localeOpen,e.engineOpen=!1,e.settingsOpen=!1})},[_("span",Fp,P(e.activeLang.flag),1),_("span",Rp,P(e.activeLang.nativeName),1),t[12]||(t[12]=_("span",{class:"ps-dots","aria-hidden":"true"},"⋮",-1))],8,Hp),e.localeOpen?(N(),E("ul",Dp,[(N(!0),E(G,null,Ee(e.switcherLangs,r=>(N(),E("li",{key:r.code,role:"option","aria-selected":String(r.code===e.locale)},[_("button",{type:"button",class:he(["ps-locale-opt",{active:r.code===e.locale}]),onClick:u=>e.setLocale(r.code)},[_("span",zp,P(r.flag),1),_("span",jp,P(r.nativeName),1),_("span",Bp,P(r.name),1)],10,Wp)],8,Up))),128))])):Y("",!0)]),_("span",Vp,[_("button",{type:"button",class:"ps-locale-btn","aria-expanded":String(e.engineOpen),"aria-label":e.tr("mapEngine"),title:e.tr("mapEngine"),onClick:t[1]||(t[1]=r=>{e.engineOpen=!e.engineOpen,e.localeOpen=!1,e.settingsOpen=!1})},[t[13]||(t[13]=_("span",{"aria-hidden":"true"},"🗺",-1)),_("span",qp,P(e.engineLabel),1),t[14]||(t[14]=_("span",{class:"ps-dots","aria-hidden":"true"},"⋮",-1))],8,Kp),e.engineOpen?(N(),E("ul",{key:0,class:"ps-locale-menu",role:"listbox","aria-label":e.tr("mapEngine")},[(N(!0),E(G,null,Ee(e.engines,r=>(N(),E("li",{key:r.id||"default",role:"option","aria-selected":String(r.id===e.userProvider)},[_("button",{type:"button",class:he(["ps-locale-opt",{active:r.id===e.userProvider}]),onClick:u=>e.setProvider(r.id)},[_("span",Jp,P(r.label),1),_("span",Zp,P(r.note),1)],10,Xp)],8,Yp))),128))],8,Gp)):Y("",!0)]),_("span",Qp,[_("button",{type:"button",class:"ps-locale-btn ps-token-btn","aria-expanded":String(e.settingsOpen),title:e.tokenStatus,onClick:t[2]||(t[2]=r=>{e.settingsOpen=!e.settingsOpen,e.localeOpen=!1,e.engineOpen=!1})},[_("span",td,P(e.tr("mapboxToken")),1),_("span",{class:he(["ps-token-dot","is-"+e.tokenSource]),"aria-hidden":"true"},null,2)],8,ed),e.settingsOpen?(N(),E("form",{key:0,class:"ps-token-panel",onSubmit:t[6]||(t[6]=Ci((...r)=>e.applyToken&&e.applyToken(...r),["prevent"]))},[_("p",od,P(e.tr("mapToken")),1),_("label",nd,[Ve(P(e.tr("tokenPaste"))+" ",1),ft(_("input",{class:"ps-token-input","onUpdate:modelValue":t[3]||(t[3]=r=>e.tokenDraft=r),placeholder:"pk.eyJ…",autocomplete:"off",spellcheck:"false"},null,512),[[Cn,e.tokenDraft,void 0,{trim:!0}]])]),_("label",sd,[Ve(P(e.tr("tokenUrlLabel"))+" ",1),ft(_("input",{class:"ps-token-input","onUpdate:modelValue":t[4]||(t[4]=r=>e.urlDraft=r),type:"url",placeholder:"https://doxa.life/api/maps/token",autocomplete:"off",spellcheck:"false"},null,512),[[Cn,e.urlDraft,void 0,{trim:!0}]])]),_("div",id,[_("button",{type:"submit",class:"ps-token-apply",disabled:e.tokenBusy},P(e.tr("tokenApply")),9,ad),_("button",{type:"button",class:"ps-token-clear",onClick:t[5]||(t[5]=(...r)=>e.clearToken&&e.clearToken(...r))},P(e.tr("tokenClear")),1)]),_("p",{class:he(["ps-token-status",{err:!!e.tokenErr}]),role:"status"},P(e.tokenErr||e.tokenStatus),3),_("p",ld,P(e.tr("tokenStoredHere")),1)],32)):Y("",!0)]),_("button",{type:"button",class:"ps-locale-btn ps-hide-header",title:e.tr("hideHeader"),"aria-label":e.tr("hideHeader"),onClick:t[7]||(t[7]=r=>e.setHeaderHidden(!0))},[t[15]||(t[15]=_("span",{"aria-hidden":"true"},"⌃",-1)),_("span",cd,P(e.tr("hideHeader")),1)],8,rd)]),toolbar:ut(()=>[e.active?(N(),E("div",pd,[_("div",dd,[_("div",ud,[_("b",null,P(e.active.label),1),_("span",fd,[Ve(P(e.active.bundle)+" · <"+P(e.active.tag)+">",1),e.active.description?(N(),E("span",hd," · "+P(e.active.description),1)):Y("",!0)])]),e.active.embed?(N(),E("button",{key:0,type:"button",class:"ps-btn","aria-expanded":String(e.embedOpen),onClick:t[8]||(t[8]=r=>e.embedOpen=!e.embedOpen)},P(e.tr("copyEmbed")),9,gd)):Y("",!0)]),e.embedOpen&&e.active.embed?(N(),E("div",bd,[_("label",null,[Ve(P(e.tr("scriptEmbed"))+" ",1),_("button",{type:"button",class:"ps-btn",onClick:t[9]||(t[9]=r=>e.copyText(e.active.embed,r.target))},P(e.tr("copy")),1)]),_("textarea",{readonly:"",value:e.active.embed},null,8,$d)])):Y("",!0)])):Y("",!0)]),default:ut(()=>[e.headerHidden?(N(),E("button",{key:0,type:"button",class:"ps-show-header",title:e.tr("showHeader"),"aria-label":e.tr("showHeader"),onClick:t[10]||(t[10]=r=>e.setHeaderHidden(!1))},[t[16]||(t[16]=_("span",{"aria-hidden":"true"},"⌄",-1)),Ve(" "+P(e.tr("showHeader")),1)],8,md)):Y("",!0),_("div",_d,[(N(!0),E(G,null,Ee(e.flatRows,r=>ft((N(),E("section",{key:r.key,class:"ps-pane",hidden:r.key!==e.activeKey},[!r.heavy||r.key===e.activeKey?(N(),E(G,{key:0},[_("div",{class:"ps-slot",ref_for:!0,ref:u=>e.setSlot(r.key,u)},null,512),r.state==="loading"?(N(),E("div",xd,P(e.tr("loading",{name:r.label})),1)):r.state==="error"?(N(),E("div",kd,[Ve(P(e.tr("couldNotLoad",{name:r.label})),1),t[17]||(t[17]=_("br",null,null,-1)),_("small",null,P(r.error),1)])):Y("",!0)],64)):Y("",!0)],8,vd)),[[Ln,r.key===e.activeKey]])),128)),e.activeKey?Y("",!0):(N(),E("div",yd,P(e.tr("chooseElement")),1))])]),_:1},8,["title","dir","nav-label","labels","header","active","onUpdate:active"])}const Sd=An(Ap,[["render",wd],["styles",[Np]]]);function Ld(){try{const e=typeof document<"u"&&document.currentScript&&document.currentScript.src||"";return e?e.replace(/[^/]+\/[^/]+$/,"").replace(/\/+$/,"")+"/":""}catch{return""}}const Nd=Ld(),Ed=_r(Sd,{configureApp(e){e.provide("psTreeBase",Nd)}});typeof customElements<"u"&&!customElements.get("plugin-studio")&&customElements.define("plugin-studio",Ed)})(); +`,Pp={5:"App shell · nested-mfe-spa",4:"Composite element",3:"Multi-view element",2:"Preset element",1:"Single element"},Vi={"nested-mfe-spa":0,"nested-elements-mfe":1,monolithic:2,parameterized:3,single:4},Tp=e=>Vi[e]!=null?5-Vi[e]:1,Cp={5:"nested-mfe-spa",4:"nested-elements-mfe",3:"monolithic",2:"parameterized",1:"single"},Hn={5:"monitor",4:"tree",3:"layers",2:"grid",1:"embed"},Ki=new Set(["doxa-research-map","doxa-simple-map","cities-internet-map","gospel-resources-map","my-upg-100-list-map","doxa-map","doxa-maps-spa","dashboard-plus-grid","research-dashboard-map","demo-map","all-people-groups","country-posters-map","key-cities-map","research-map-plus-grid","gospel-internet-board"]),qi=new Set(["big-picture"]),Ho={};for(const[e,t]of Object.entries(Object.assign({"../../library/i18n/locales/ar/studio.json":Er,"../../library/i18n/locales/de/studio.json":Pr,"../../library/i18n/locales/en/studio.json":Tr,"../../library/i18n/locales/es/studio.json":Cr,"../../library/i18n/locales/fr/studio.json":Mr,"../../library/i18n/locales/hi/studio.json":Ar,"../../library/i18n/locales/it/studio.json":Or,"../../library/i18n/locales/pt/studio.json":Ir,"../../library/i18n/locales/ro/studio.json":Hr,"../../library/i18n/locales/ru/studio.json":Fr,"../../library/i18n/locales/zh/studio.json":Rr}))){const o=e.match(/locales\/([^/]+)\/studio\.json$/);o&&(Ho[o[1]]=t)}const Mp={"doxa-maps-spa/doxa-maps-spa":"Research Gallery"},Vt={};function Gi(e,t){return Vt[e]||(Vt[e]=new Promise((o,n)=>{const s=document.createElement("script");s.src=e,(/^\/plugin-designs\//.test(e)||/\/index\.js(\?|$)/.test(e))&&(s.type="module"),s.onload=()=>o(),s.onerror=()=>{delete Vt[e],n(new Error("failed to load "+e))},document.head.appendChild(s)})),Vt[e]}function Yi(e,t){return typeof customElements>"u"||customElements.get(e)?Promise.resolve():Promise.race([customElements.whenDefined(e),new Promise((o,n)=>setTimeout(()=>{customElements.get(e)||n(new Error("<"+e+"> never registered (bundle loaded but defined no element)"))},15e3))])}const Ap=$o({name:"PluginStudio",inheritAttrs:!1,components:{VerticalTabsLayout:zc,StudioTree:kp},props:{treeBase:{type:String,default:""},profileConfig:{type:[String,Object],default:""},provider:{type:String,default:""},heading:{type:String,default:""},tokenUrl:{type:String,default:""},tk:{type:String,default:""}},setup(){return Mn(Ep,"plugin-studio"),{injectedBase:Tt("psTreeBase","")}},data(){return{activeKey:"",embedOpen:!1,locale:this.initialLocale(),localeOpen:!1,settingsOpen:!1,headerHidden:mt(ji)==="1",engineOpen:!1,userProvider:mt(Bi),tokenBusy:!1,tokenErr:"",tokenDraft:mt(Oo),urlDraft:mt(Io),userTk:mt(Oo),userTokenUrl:mt(Io),fetchedTk:"",bakedTk:"",hostProvider:"",switcherLangs:Mo,rows:[],manifestBundles:[]}},computed:{cfg(){let e=this.profileConfig;if(typeof e=="string")try{e=e?JSON.parse(e):{}}catch{e={}}return e&&typeof e=="object"?e:{}},base(){const e=(this.treeBase||this.cfg.treeBase||this.injectedBase||"").trim();return e?e.replace(/\/+$/,"")+"/":""},flatRows(){return this.rows},groups(){const e={};for(const t of this.rows)(e[t.cap]=e[t.cap]||[]).push(t);return[5,4,3,2,1].filter(t=>e[t]&&e[t].length).map(t=>({cap:t,label:Pp[t]||"capability "+t,rows:e[t]}))},treeSections(){const e=new Map(this.compositionTrees.map(a=>[a.nodes[0].selects,a])),t=new Map;for(const a of this.rows)t.has(a.bundle)||t.set(a.bundle,[]),t.get(a.bundle).push(a);const o=[...t.entries()].map(([a,l])=>({bundle:a,rows:l,cap:Math.max(...l.map(r=>r.cap)),stage:l[0].stage})),n=o.filter(a=>a.stage!=="production").sort((a,l)=>l.cap-a.cap||a.bundle.localeCompare(l.bundle)),s=o.filter(a=>a.stage==="production"),i=[5,4,3,2,1].map(a=>({cap:a,group:s.filter(l=>l.cap===a).sort((l,r)=>l.bundle.localeCompare(r.bundle))}));return i.push({cap:"experimental",group:n}),i.map(({cap:a,group:l})=>{if(!l.length)return null;const r=[],u=(p,h,v)=>{const y=e.get(p.key);if(r.push({id:p.key,parent:v,depth:h,label:p.label,desc:p.tag,icon:p.icon,target:p.key,canonical:!0,kids:y?y.nodes[0].kids:0,title:p.label+" · <"+p.tag+"> · CAP "+p.cap+" "+this.tr("cap"+p.cap)}),!y)return;const H=L=>L===0?p.key:p.key+">"+L;for(const L of y.nodes.slice(1))r.push({id:H(L.id),parent:H(L.ancestors[L.ancestors.length-1]),depth:h+L.depth,label:L.label,part:!!L.part,target:L.selects||"",canonical:!1,icon:L.part?"dots":Hn[L.cap]||"embed",desc:L.part?this.tr("noStandalone"):"cap "+L.cap+" · "+L.tag,kids:L.kids||0,title:L.part?L.label+" · "+this.tr("partOf",{name:p.label}):L.label+" · <"+L.tag+"> · CAP "+L.cap+" "+this.tr("cap"+L.cap)})};for(const p of l){const h=[...p.rows].sort((y,H)=>H.cap-y.cap||y.label.localeCompare(H.label));if(h.length===1){u(h[0],0,"");continue}const v="bundle:"+p.bundle;r.push({id:v,parent:"",depth:0,label:p.bundle,desc:this.tr("elementsCount",{n:h.length}),icon:"folder",target:h[0].key,canonical:!1,folder:!0,kids:h.length,title:p.bundle+" · plugin-designs/"+p.bundle+"/ · "+h.length+" "+this.tr("elements")});for(const y of h)u(y,1,v)}return a==="experimental"?{id:"stage-experimental",cap:0,label:this.tr("stageExperimental"),title:this.tr("stageExperimental"),icon:"layers",nodes:r}:{id:"cap-"+a,cap:a,label:this.tr("cap"+a),title:this.tr("cap"+a)+" · "+(Cp[a]||""),icon:Hn[a]||"embed",nodes:r}}).filter(Boolean)},compositionTrees(){const e=[],t=(o,n,s,i,a)=>{const l=this.manifestBundles.find(v=>v.bundle===o.bundle),r=o.cap>=4&&l&&l.composes||[],u=[],p=[],h=new Set;for(const v of r){const y=this.resolveRef(v,o.bundle);if(!y){p.push(v);continue}y.key===o.key||h.has(y.key)||(h.add(y.key),u.push(y))}u.sort((v,y)=>y.cap-v.cap||v.label.localeCompare(y.label));for(const v of u){const y={id:i.length,label:v.label,tag:v.tag,cap:v.cap,selects:v.key,depth:n+1,ancestors:a,kids:0};i.push(y);const H=i.length;s.has(v.key)||t(v,n+1,new Set([...s,v.key]),i,[...a,y.id]),y.kids=i.filter((L,ee)=>ee>=H&&L.depth===n+2).length}for(const v of p)i.push({id:i.length,label:v,part:!0,selects:o.key,depth:n+1,ancestors:a,kids:0})};for(const o of this.manifestBundles){if(!o.composes||!o.composes.length||qi.has(o.bundle))continue;const n=this.rows.find(i=>i.bundle===o.bundle);if(!n)continue;const s=[{id:0,label:n.label,tag:n.tag,cap:n.cap,selects:n.key,depth:0,ancestors:[]}];t(n,0,new Set([n.key]),s,[0]),s[0].kids=s.filter(i=>i.depth===1).length,s.length>1&&e.push({bundle:o.bundle,nodes:s})}return e},active(){return this.rows.find(e=>e.key===this.activeKey)||null},effectiveTk(){return this.userTk||this.fetchedTk||this.tk||this.cfg.tk||this.bakedTk||""},effectiveProvider(){const e=String(this.userProvider||this.provider||this.cfg.provider||"").toLowerCase().trim();return e==="maplibre"||e==="mapbox"?e:""},engines(){return[{id:"",label:this.tr("engineDefault"),note:""},{id:"mapbox",label:"Mapbox",note:this.tr("engineMapboxNote")},{id:"maplibre",label:"MapLibre",note:this.tr("engineMaplibreNote")}]},engineLabel(){return this.userProvider==="mapbox"?"Mapbox":this.userProvider==="maplibre"?"MapLibre":this.tr("engineDefault")},tokenSource(){return this.userTk?"yours":this.fetchedTk?"url":this.tk||this.cfg.tk||this.bakedTk?"built":"none"},tokenStatus(){return this.effectiveProvider==="maplibre"?this.tr("tokenNotNeeded"):this.tokenSource==="yours"?this.tr("tokenSourceYours"):this.tokenSource==="url"?this.tr("tokenSourceUrl",{url:this.userTokenUrl}):this.tokenSource==="built"?this.tr("tokenSourceBuilt"):this.tr("tokenSourceNone")},countLabel(){const e=new Set(this.rows.map(t=>t.bundle)).size;return this.tr("countLabel",{bundles:e,elements:this.rows.length})},activeLang(){return yp(this.locale)||{code:this.locale,flag:"🌐",nativeName:this.locale}},uiDir(){return(this.activeLang&&this.activeLang.dir)==="rtl"?"rtl":"ltr"}},mounted(){this.bakedTk=typeof window<"u"&&window.MAP_TOKEN||"",this.hostProvider=typeof window<"u"&&typeof window.MAP_PROVIDER=="string"?window.MAP_PROVIDER:"",this.publishProvider(),this.userTk?this.publishToken():(this.userTokenUrl||this.tokenUrl||this.cfg.tokenUrl)&&this.fetchToken(this.userTokenUrl||this.tokenUrl||this.cfg.tokenUrl).then(e=>{e&&e!==this.fetchedTk&&(this.fetchedTk=e,this.publishToken(),this.remountPanes())}).catch(()=>{}),this.loadManifest()},methods:{async fetchToken(e){if(!/^https?:\/\//i.test(e))throw new Error("not an http(s) URL");let t;try{t=await fetch(e,{cache:"no-store",credentials:"same-origin"})}catch{throw new Error("the request was blocked or the server did not answer (cross-origin rules can do this)")}if(!t.ok)throw new Error("HTTP "+t.status);const o=(await t.text()).trim();let n=o;try{const s=JSON.parse(o);n=s&&(s.token||s.tk||s.accessToken)||(typeof s=="string"?s:"")}catch{}if(n=String(n||"").trim(),n.startsWith("sk."))throw new Error(this.tr("tokenSecret"));if(!n.startsWith("pk."))throw new Error(this.tr("tokenNotPk"));return n},async applyToken(){this.tokenErr="";const e=this.tokenDraft,t=this.urlDraft;if(e.startsWith("sk.")){this.tokenErr=this.tr("tokenSecret");return}if(e&&!e.startsWith("pk.")){this.tokenErr=this.tr("tokenNotPk");return}this.tokenBusy=!0;try{let o="";if(!e&&t)try{o=await this.fetchToken(t)}catch(n){this.tokenErr=this.tr("tokenUrlFailed",{why:n.message});return}this.userTk=e,this.userTokenUrl=e?"":t,this.fetchedTk=o,_t(Oo,this.userTk),_t(Io,this.userTokenUrl),this.publishToken(),this.remountPanes(),this.settingsOpen=!1}finally{this.tokenBusy=!1}},setHeaderHidden(e){this.headerHidden=!!e,this.settingsOpen=!1,this.engineOpen=!1,this.localeOpen=!1,_t(ji,e?"1":"")},setProvider(e){this.engineOpen=!1,e!==this.userProvider&&(this.userProvider=e,_t(Bi,e),this.publishProvider(),this.remountPanes())},publishProvider(){typeof window>"u"||(this.effectiveProvider?window.MAP_PROVIDER=this.effectiveProvider:this.hostProvider?window.MAP_PROVIDER=this.hostProvider:"MAP_PROVIDER"in window&&delete window.MAP_PROVIDER)},clearToken(){this.tokenDraft="",this.urlDraft="",this.tokenErr="",this.userTk="",this.userTokenUrl="",this.fetchedTk="",_t(Oo,""),_t(Io,""),this.publishToken(),this.remountPanes()},publishToken(){typeof window>"u"||(this.effectiveTk?(Wi(this.effectiveTk),window.MAP_TOKEN!==this.effectiveTk&&(window.MAP_TOKEN=this.effectiveTk)):Lp())},remountPanes(){for(const t of this.rows)t.mounted&&this.releaseRow(t);const e=this.active;e&&this.$nextTick(()=>{this.activeKey===e.key&&this.mountElement(e)})},tr(e,t){const o=(this.locale||"en").split("-")[0];let n=(Ho[this.locale]||{})[e]||(Ho[o]||{})[e]||(Ho.en||{})[e]||e;if(t)for(const s in t)n=n.split("{"+s+"}").join(String(t[s]));return n},resolveRef(e,t){return t&&this.rows.find(o=>o.key===t+"/"+e)||this.rows.find(o=>o.key===e)||this.rows.find(o=>o.tag===e)||this.rows.find(o=>o.bundle===e)||null},setSlot(e,t){t&&(this._slots=Object.assign(this._slots||{},{[e]:t}))},initialLocale(){let e=this.profileConfig;if(typeof e=="string")try{e=e?JSON.parse(e):{}}catch{e={}}let t="";try{const n=new URLSearchParams(window.location.search);t=n.get("lang")||n.get("locale")||""}catch{}const o=e&&(e.locale||e.lang)||t;return o?In(o):wp()},paneConfig(e,t){const o={profile:e.profile,instanceId:"ps-"+e.key.replace(/\//g,"-"),locale:t};this.effectiveTk&&(o.tk=this.effectiveTk);const n=this.userTokenUrl||this.tokenUrl||this.cfg.tokenUrl;return n&&(o.tokenUrl=n),this.effectiveProvider&&(o.provider=this.effectiveProvider),this.base&&(o.treeBase=this.base),o},setLocale(e){this.locale=e,this.localeOpen=!1,Sp(e);try{for(const t of this.rows){if(!t.mounted)continue;const o=this._slots&&this._slots[t.key],n=o&&o.firstElementChild;n&&n.setAttribute&&n.setAttribute("profile-config",JSON.stringify(this.paneConfig(t,e)))}}catch{}},resolve(e){const t=String(e);if(/^(https?:)?\/\//.test(t)||t.startsWith("/"))return t;const o=t.replace(/^\.\//,"");return this.base?this.base.replace(/\/+$/,"")+"/"+o:"../"+o},loadManifest(){const e=o=>{this.manifestBundles=o&&o.bundles||[],this.rows=this.rowsFromManifest(o),this.setupWidgets(),this.route()},t=typeof window<"u"&&window.__psBaked||null;if(typeof fetch=="function"&&typeof location<"u"&&location.protocol!=="file:"){const o=this.base?this.resolve("manifest.json"):"../manifest.json";fetch(o,{cache:"no-cache"}).then(n=>n.ok?n.json():null).then(n=>e(n||t||{bundles:[]})).catch(()=>e(t||{bundles:[]}))}else e(t||{bundles:[]})},rowsFromManifest(e){const t=[];for(const o of e.bundles||[])if(!(o.bundle==="plugin-studio"||qi.has(o.bundle)))for(const n of o.profiles||[]){const s=o.elements&&o.elements.length?o.elements:null,i=(n.element&&(!s||s.includes(n.element))?n.element:null)||s&&s[0]||n.element||o.bundle,a=Tp(n.type||"single"),l=Ki.has(i)||Ki.has(o.bundle)||n.heavy===!0;t.push({key:o.bundle+"/"+n.profile,bundle:o.bundle,stage:o.stage==="production"?"production":"experimental",label:Mp[o.bundle+"/"+n.profile]||n.profile,profile:n.profile,tag:i,cap:a,icon:Hn[a]||"embed",description:n.description||"",widget:n.widget&&["bottom-right","bottom-left","top-right","top-left"].includes(n.widget.corner)?n.widget.corner:"",heavy:l,bundleJs:o.scriptUrl||o.bundle+"/"+o.bundle+".js",embed:n.embed&&n.embed.script||"",mounted:!1,state:"idle",error:""})}return t.sort((o,n)=>n.cap-o.cap||o.bundle.localeCompare(n.bundle)||o.label.localeCompare(n.label)),t},route(){const e=(typeof location<"u"&&location.hash||"").replace(/^#\/?/,"");if(e&&this.rows.some(o=>o.key===e)){this.select(e);return}const t=this.readLastTab();if(t&&this.rows.some(o=>o.key===t)){this.select(t);return}this.rows.length&&this.select(this.rows[0].key)},storageKey(){return"dx-studio-tab:"+(typeof location<"u"&&location.pathname||"")},readLastTab(){try{return window.localStorage.getItem(this.storageKey())||""}catch{return""}},writeLastTab(e){try{window.localStorage.setItem(this.storageKey(),e)}catch{}},select(e){if(!this.rows.some(s=>s.key===e))return;const t=this.rows.find(s=>s.key===e);if(t&&t.widget){this.openWidget(t,!0);return}const o=this.activeKey;if(this.activeKey=e,this.embedOpen=!1,o&&o!==e){const s=this.rows.find(i=>i.key===o);s&&s.heavy&&s.mounted&&this.releaseRow(s)}const n=this.rows.find(s=>s.key===e);n&&(this.writeLastTab(e),n.mounted||this.$nextTick(()=>{this.activeKey===n.key&&this.mountElement(n)}))},releaseRow(e){try{const t=this._slots&&this._slots[e.key];t&&(t.innerHTML="")}catch{}this._slots&&delete this._slots[e.key],e.mounted=!1,e.state="idle",e.error=""},widgetStore(){return window.__doxaStudioWidgets||(window.__doxaStudioWidgets={hosts:{},els:{}}),window.__doxaStudioWidgets},widgetHost(e){const t=this.widgetStore();if(t.hosts[e]&&t.hosts[e].isConnected)return t.hosts[e];const o=document.createElement("div");o.setAttribute("data-studio-widgets",e);const[n,s]=e.split("-");return o.style.cssText=`position:fixed;${n}:max(12px,env(safe-area-inset-${n}));${s}:max(12px,env(safe-area-inset-${s}));z-index:2147483647;display:flex;flex-direction:column;align-items:${s==="right"?"flex-end":"flex-start"};gap:8px;`,document.body.appendChild(o),t.hosts[e]=o,o},setupWidgets(){for(const e of this.rows.filter(t=>t.widget)){const t=this.widgetStore(),o=this.widgetHost(e.widget);let n=o.querySelector(`[data-widget="${e.key}"]`);if(!n){n=document.createElement("div"),n.setAttribute("data-widget",e.key),n.style.cssText="display:flex;flex-direction:column;align-items:inherit;gap:6px;";const i=document.createElement("div");i.setAttribute("data-widget-panel",""),i.style.cssText="display:none;width:min(380px,calc(100vw - 24px));height:min(520px,calc(100vh - 80px));height:min(520px,calc(100dvh - 80px - env(safe-area-inset-top) - env(safe-area-inset-bottom)));position:relative;background:#fff;border-radius:10px;box-shadow:0 8px 30px rgba(0,0,0,.25);overflow:hidden;";const a=document.createElement("button");a.type="button";const l="widget:"+e.key,r=this.tr(l);a.textContent=r!==l?r:e.label,a.setAttribute("aria-expanded","false"),a.style.cssText="font:600 13px system-ui,sans-serif;padding:8px 14px;border-radius:999px;border:1px solid #30363d;background:#0d1117;color:#e6edf3;cursor:pointer;box-shadow:0 2px 10px rgba(0,0,0,.25);",a.addEventListener("click",()=>this.openWidget(e,i.style.display==="none")),n.appendChild(i),n.appendChild(a),o.appendChild(n)}t.els[e.key]&&!n.querySelector(e.tag)&&n.querySelector("[data-widget-panel]").appendChild(t.els[e.key]);let s=!1;try{s=localStorage.getItem("plugin-studio:widget-open:"+e.key)==="1"}catch{}s&&this.openWidget(e,!0)}},openWidget(e,t){const n=this.widgetHost(e.widget).querySelector(`[data-widget="${e.key}"]`);if(!n){this.setupWidgets();return}const s=n.querySelector("[data-widget-panel]"),i=n.querySelector("button");s.style.display=t?"block":"none",i.setAttribute("aria-expanded",t?"true":"false");try{localStorage.setItem("plugin-studio:widget-open:"+e.key,t?"1":"0")}catch{}const a=this.widgetStore();!t||a.els[e.key]||Gi(this.resolve(e.bundleJs)).then(()=>Yi(e.tag)).then(()=>{if(a.els[e.key])return;const l=document.createElement(e.tag);l.setAttribute("profile-config",JSON.stringify(this.paneConfig(e,this.locale))),this.base&&l.setAttribute("tree-base",this.base.replace(/\/+$/,"")),l.style.cssText="display:block;position:absolute;inset:0;width:100%;height:100%;overflow-y:auto;overscroll-behavior:contain;",l.addEventListener("recording",r=>{const u=!!(Array.isArray(r.detail)?r.detail[0]:r.detail),p=n.querySelector(":scope > button");p&&(p.dataset.label||(p.dataset.label=p.textContent),p.textContent=u?"● "+p.dataset.label:p.dataset.label,p.style.background=u?"#7f1d1d":"#0d1117",p.style.borderColor=u?"#ef4444":"#30363d",p.setAttribute("data-listening",u?"true":"false"))}),a.els[e.key]=l,s.appendChild(l)}).catch(l=>{s.textContent=l&&l.message||String(l)})},mountElement(e){e.mounted=!0,e.state="loading";const t=this.resolve(e.bundleJs);Gi(t).then(()=>Yi(e.tag)).then(()=>{try{if(e.heavy&&this.activeKey!==e.key){e.mounted=!1,e.state="idle";return}const o=this._slots&&this._slots[e.key];if(!o){e.state="error",e.error="no slot";return}o.innerHTML="";const n=document.createElement(e.tag);n.setAttribute("profile-config",JSON.stringify(this.paneConfig(e,this.locale))),this.base&&n.setAttribute("tree-base",this.base.replace(/\/+$/,"")),n.style.cssText="display:block;position:absolute;inset:0;width:100%;height:100%;",o.appendChild(n),e.state="ready"}catch(o){e.state="error",e.error="mount failed: "+(o&&o.message||String(o))}}).catch(o=>{e.state="error",e.error=o&&o.message||String(o)})},copyText(e,t){const o=()=>{const n=t.textContent;t.textContent=this.tr("copied"),setTimeout(()=>{t.textContent=n},1200)};if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(e).then(o,()=>{});else try{const n=document.createElement("textarea");n.value=e,document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n),o()}catch{}}}}),Op={class:"ps-count"},Ip={class:"ps-locale"},Hp=["aria-expanded","aria-label"],Fp={class:"ps-flag"},Rp={class:"ps-locale-name"},Dp={key:0,class:"ps-locale-menu",role:"listbox"},Up=["aria-selected"],Wp=["onClick"],zp={class:"ps-flag"},jp={class:"ps-locale-name"},Bp={class:"ps-locale-en"},Vp={class:"ps-locale ps-engine"},Kp=["aria-expanded","aria-label","title"],qp={class:"ps-locale-name"},Gp=["aria-label"],Yp=["aria-selected"],Xp=["onClick"],Jp={class:"ps-locale-name"},Zp={class:"ps-locale-en"},Qp={class:"ps-token"},ed=["aria-expanded","title"],td={class:"ps-locale-name"},od={class:"ps-token-head"},nd={class:"ps-token-label"},sd={class:"ps-token-label"},id={class:"ps-token-row"},ad=["disabled"],ld={class:"ps-token-note"},rd=["title","aria-label"],cd={class:"ps-locale-name"},pd={key:0,class:"ps-toolbar"},dd={class:"ps-bar"},ud={class:"ps-bar-t"},fd={class:"ps-bar-sub"},hd={key:0},gd=["aria-expanded"],bd={key:0,class:"ps-embed"},$d=["value"],md=["title","aria-label"],_d={class:"ps-stage"},vd=["hidden"],xd={key:0,class:"ps-hint"},kd={key:1,class:"ps-hint err"},yd={key:0,class:"ps-hint"};function wd(e,t,o,n,s,i){const a=Os("StudioTree"),l=Os("VerticalTabsLayout");return N(),yo(l,{title:e.heading||e.tr("title"),dir:e.uiDir,"nav-label":e.tr("navLabel"),labels:{toggleList:e.tr("toggleList"),openViews:e.tr("openViews"),expandList:e.tr("expandList"),collapseList:e.tr("collapseList"),collapse:e.tr("collapse")},header:!e.headerHidden,active:e.activeKey,"onUpdate:active":e.select},{rail:ut(({collapsed:r,expand:u,pick:p})=>[me(a,{sections:e.treeSections,active:e.activeKey,collapsed:r,expand:u,pick:p,strings:{filterPlaceholder:e.tr("filterPlaceholder"),collapseAll:e.tr("collapseAll"),noMatch:e.tr("noMatch"),treeLabel:e.tr("navLabel"),openSection:e.tr("openSection"),part:e.tr("part")}},null,8,["sections","active","collapsed","expand","pick","strings"])]),brand:ut(()=>[...t[11]||(t[11]=[_("span",{class:"ps-logo","aria-hidden":"true"},[_("svg",{viewBox:"0 0 24 24",width:"22",height:"22",fill:"none",stroke:"#92b195","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[_("path",{d:"M10 3v3M14 3v3M7 6h10v5a5 5 0 0 1-10 0V6Z"}),_("path",{d:"M12 16v5"})])],-1)])]),meta:ut(()=>[_("span",Op,P(e.countLabel),1),_("span",Ip,[_("button",{type:"button",class:"ps-locale-btn","aria-expanded":String(e.localeOpen),"aria-label":e.tr("changeLanguage"),onClick:t[0]||(t[0]=r=>{e.localeOpen=!e.localeOpen,e.engineOpen=!1,e.settingsOpen=!1})},[_("span",Fp,P(e.activeLang.flag),1),_("span",Rp,P(e.activeLang.nativeName),1),t[12]||(t[12]=_("span",{class:"ps-dots","aria-hidden":"true"},"⋮",-1))],8,Hp),e.localeOpen?(N(),E("ul",Dp,[(N(!0),E(G,null,Ee(e.switcherLangs,r=>(N(),E("li",{key:r.code,role:"option","aria-selected":String(r.code===e.locale)},[_("button",{type:"button",class:he(["ps-locale-opt",{active:r.code===e.locale}]),onClick:u=>e.setLocale(r.code)},[_("span",zp,P(r.flag),1),_("span",jp,P(r.nativeName),1),_("span",Bp,P(r.name),1)],10,Wp)],8,Up))),128))])):Y("",!0)]),_("span",Vp,[_("button",{type:"button",class:"ps-locale-btn","aria-expanded":String(e.engineOpen),"aria-label":e.tr("mapEngine"),title:e.tr("mapEngine"),onClick:t[1]||(t[1]=r=>{e.engineOpen=!e.engineOpen,e.localeOpen=!1,e.settingsOpen=!1})},[t[13]||(t[13]=_("span",{"aria-hidden":"true"},"🗺",-1)),_("span",qp,P(e.engineLabel),1),t[14]||(t[14]=_("span",{class:"ps-dots","aria-hidden":"true"},"⋮",-1))],8,Kp),e.engineOpen?(N(),E("ul",{key:0,class:"ps-locale-menu",role:"listbox","aria-label":e.tr("mapEngine")},[(N(!0),E(G,null,Ee(e.engines,r=>(N(),E("li",{key:r.id||"default",role:"option","aria-selected":String(r.id===e.userProvider)},[_("button",{type:"button",class:he(["ps-locale-opt",{active:r.id===e.userProvider}]),onClick:u=>e.setProvider(r.id)},[_("span",Jp,P(r.label),1),_("span",Zp,P(r.note),1)],10,Xp)],8,Yp))),128))],8,Gp)):Y("",!0)]),_("span",Qp,[_("button",{type:"button",class:"ps-locale-btn ps-token-btn","aria-expanded":String(e.settingsOpen),title:e.tokenStatus,onClick:t[2]||(t[2]=r=>{e.settingsOpen=!e.settingsOpen,e.localeOpen=!1,e.engineOpen=!1})},[_("span",td,P(e.tr("mapboxToken")),1),_("span",{class:he(["ps-token-dot","is-"+e.tokenSource]),"aria-hidden":"true"},null,2)],8,ed),e.settingsOpen?(N(),E("form",{key:0,class:"ps-token-panel",onSubmit:t[6]||(t[6]=Ci((...r)=>e.applyToken&&e.applyToken(...r),["prevent"]))},[_("p",od,P(e.tr("mapToken")),1),_("label",nd,[Ve(P(e.tr("tokenPaste"))+" ",1),ft(_("input",{class:"ps-token-input","onUpdate:modelValue":t[3]||(t[3]=r=>e.tokenDraft=r),placeholder:"pk.eyJ…",autocomplete:"off",spellcheck:"false"},null,512),[[Cn,e.tokenDraft,void 0,{trim:!0}]])]),_("label",sd,[Ve(P(e.tr("tokenUrlLabel"))+" ",1),ft(_("input",{class:"ps-token-input","onUpdate:modelValue":t[4]||(t[4]=r=>e.urlDraft=r),type:"url",placeholder:"https://doxa.life/api/maps/token",autocomplete:"off",spellcheck:"false"},null,512),[[Cn,e.urlDraft,void 0,{trim:!0}]])]),_("div",id,[_("button",{type:"submit",class:"ps-token-apply",disabled:e.tokenBusy},P(e.tr("tokenApply")),9,ad),_("button",{type:"button",class:"ps-token-clear",onClick:t[5]||(t[5]=(...r)=>e.clearToken&&e.clearToken(...r))},P(e.tr("tokenClear")),1)]),_("p",{class:he(["ps-token-status",{err:!!e.tokenErr}]),role:"status"},P(e.tokenErr||e.tokenStatus),3),_("p",ld,P(e.tr("tokenStoredHere")),1)],32)):Y("",!0)]),_("button",{type:"button",class:"ps-locale-btn ps-hide-header",title:e.tr("hideHeader"),"aria-label":e.tr("hideHeader"),onClick:t[7]||(t[7]=r=>e.setHeaderHidden(!0))},[t[15]||(t[15]=_("span",{"aria-hidden":"true"},"⌃",-1)),_("span",cd,P(e.tr("hideHeader")),1)],8,rd)]),toolbar:ut(()=>[e.active?(N(),E("div",pd,[_("div",dd,[_("div",ud,[_("b",null,P(e.active.label),1),_("span",fd,[Ve(P(e.active.bundle)+" · <"+P(e.active.tag)+">",1),e.active.description?(N(),E("span",hd," · "+P(e.active.description),1)):Y("",!0)])]),e.active.embed?(N(),E("button",{key:0,type:"button",class:"ps-btn","aria-expanded":String(e.embedOpen),onClick:t[8]||(t[8]=r=>e.embedOpen=!e.embedOpen)},P(e.tr("copyEmbed")),9,gd)):Y("",!0)]),e.embedOpen&&e.active.embed?(N(),E("div",bd,[_("label",null,[Ve(P(e.tr("scriptEmbed"))+" ",1),_("button",{type:"button",class:"ps-btn",onClick:t[9]||(t[9]=r=>e.copyText(e.active.embed,r.target))},P(e.tr("copy")),1)]),_("textarea",{readonly:"",value:e.active.embed},null,8,$d)])):Y("",!0)])):Y("",!0)]),default:ut(()=>[e.headerHidden?(N(),E("button",{key:0,type:"button",class:"ps-show-header",title:e.tr("showHeader"),"aria-label":e.tr("showHeader"),onClick:t[10]||(t[10]=r=>e.setHeaderHidden(!1))},[t[16]||(t[16]=_("span",{"aria-hidden":"true"},"⌄",-1)),Ve(" "+P(e.tr("showHeader")),1)],8,md)):Y("",!0),_("div",_d,[(N(!0),E(G,null,Ee(e.flatRows,r=>ft((N(),E("section",{key:r.key,class:"ps-pane",hidden:r.key!==e.activeKey},[!r.heavy||r.key===e.activeKey?(N(),E(G,{key:0},[_("div",{class:"ps-slot",ref_for:!0,ref:u=>e.setSlot(r.key,u)},null,512),r.state==="loading"?(N(),E("div",xd,P(e.tr("loading",{name:r.label})),1)):r.state==="error"?(N(),E("div",kd,[Ve(P(e.tr("couldNotLoad",{name:r.label})),1),t[17]||(t[17]=_("br",null,null,-1)),_("small",null,P(r.error),1)])):Y("",!0)],64)):Y("",!0)],8,vd)),[[Ln,r.key===e.activeKey]])),128)),e.activeKey?Y("",!0):(N(),E("div",yd,P(e.tr("chooseElement")),1))])]),_:1},8,["title","dir","nav-label","labels","header","active","onUpdate:active"])}const Sd=An(Ap,[["render",wd],["styles",[Np]]]);function Ld(){try{const e=typeof document<"u"&&document.currentScript&&document.currentScript.src||"";return e?e.replace(/[^/]+\/[^/]+$/,"").replace(/\/+$/,"")+"/":""}catch{return""}}const Nd=Ld(),Ed=_r(Sd,{configureApp(e){e.provide("psTreeBase",Nd)}});typeof customElements<"u"&&!customElements.get("plugin-studio")&&customElements.define("plugin-studio",Ed)})(); diff --git a/public/dx-maps/plugin-studio/plugin-studio/index.html b/public/dx-maps/plugin-studio/plugin-studio/index.html index 1c135101..0c5bfee4 100644 --- a/public/dx-maps/plugin-studio/plugin-studio/index.html +++ b/public/dx-maps/plugin-studio/plugin-studio/index.html @@ -32,7 +32,7 @@ - + - + - +