@yuno-payments/dashboard-embed-sdk 1.4.0-BETA.10 → 1.4.0-BETA.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +0 -1
- package/dist/index.js +1 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -27,7 +27,6 @@ var Dashboard = class {
|
|
|
27
27
|
// iframe. Ref-counted to survive stacked overlays.
|
|
28
28
|
this.overlayCount = 0;
|
|
29
29
|
this.savedIframeCss = null;
|
|
30
|
-
this.overlayRevealTimer = null;
|
|
31
30
|
this.baseUrl = config.baseUrl;
|
|
32
31
|
this.initialTheme = config.theme;
|
|
33
32
|
this.initialLang = config.lang;
|
|
@@ -116,10 +115,6 @@ var Dashboard = class {
|
|
|
116
115
|
this.ready = false;
|
|
117
116
|
this.overlayCount = 0;
|
|
118
117
|
this.savedIframeCss = null;
|
|
119
|
-
if (this.overlayRevealTimer) {
|
|
120
|
-
clearTimeout(this.overlayRevealTimer);
|
|
121
|
-
this.overlayRevealTimer = null;
|
|
122
|
-
}
|
|
123
118
|
}
|
|
124
119
|
// Runs a host callback, swallowing sync throws and async rejections so a
|
|
125
120
|
// misbehaving host handler can never break the SDK's message loop.
|
|
@@ -184,38 +179,14 @@ var Dashboard = class {
|
|
|
184
179
|
zIndex: "2147483647",
|
|
185
180
|
// Transparent so the host page shows through wherever the dashboard
|
|
186
181
|
// doesn't paint (the offset regions).
|
|
187
|
-
background: "transparent"
|
|
188
|
-
// Mask the cross-document reflow: expanding the iframe and the
|
|
189
|
-
// dashboard insetting its content happen a frame apart, which flickers.
|
|
190
|
-
// Hide the iframe INSTANTLY (no transition here — a transition would
|
|
191
|
-
// animate the hide and leave the reflow visible mid-fade) and fade it
|
|
192
|
-
// back in once the inset has settled.
|
|
193
|
-
transition: "none",
|
|
194
|
-
opacity: "0"
|
|
182
|
+
background: "transparent"
|
|
195
183
|
});
|
|
196
184
|
this.post({ action: "overlay-mode", active: true, offset });
|
|
197
|
-
if (this.overlayRevealTimer) clearTimeout(this.overlayRevealTimer);
|
|
198
|
-
this.overlayRevealTimer = setTimeout(() => {
|
|
199
|
-
this.iframe.style.transition = "opacity 0.15s ease";
|
|
200
|
-
this.iframe.style.opacity = "1";
|
|
201
|
-
this.overlayRevealTimer = null;
|
|
202
|
-
}, 100);
|
|
203
185
|
}
|
|
204
186
|
restoreIframe() {
|
|
205
|
-
if (this.overlayRevealTimer) {
|
|
206
|
-
clearTimeout(this.overlayRevealTimer);
|
|
207
|
-
this.overlayRevealTimer = null;
|
|
208
|
-
}
|
|
209
187
|
this.iframe.style.cssText = this.savedIframeCss ?? "";
|
|
210
188
|
this.savedIframeCss = null;
|
|
211
|
-
this.iframe.style.transition = "none";
|
|
212
|
-
this.iframe.style.opacity = "0";
|
|
213
189
|
this.post({ action: "overlay-mode", active: false });
|
|
214
|
-
this.overlayRevealTimer = setTimeout(() => {
|
|
215
|
-
this.iframe.style.transition = "opacity 0.15s ease";
|
|
216
|
-
this.iframe.style.opacity = "1";
|
|
217
|
-
this.overlayRevealTimer = null;
|
|
218
|
-
}, 100);
|
|
219
190
|
}
|
|
220
191
|
post(message) {
|
|
221
192
|
if (this.ready && this.iframe.contentWindow) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dashboard.ts","../src/singleton.ts"],"sourcesContent":["import type { DashboardTheme, DashboardConfig, DashboardEvents } from \"./types\";\n\nconst EMBED_EVENT_MESSAGE_TYPE = \"yuno-dashboard:embed-event\";\nconst HOST_CAPABILITIES_MESSAGE_TYPE = \"yuno-dashboard:host-capabilities\";\n\ntype EmbedEventHandler = (event: {\n status?: unknown;\n payload?: unknown;\n}) => void | Promise<void>;\n\n// Build the capability map the dashboard reads to decide which actions the\n// host owns: { connections: { created: true }, ... } for every provided handler.\nfunction buildCapabilities(\n events?: DashboardEvents,\n): Record<string, Record<string, boolean>> {\n const capabilities: Record<string, Record<string, boolean>> = {};\n if (!events) return capabilities;\n const groups = events as Record<string, Record<string, unknown> | undefined>;\n for (const domain of Object.keys(groups)) {\n const group = groups[domain];\n if (!group) continue;\n for (const action of Object.keys(group)) {\n if (typeof group[action] === \"function\") {\n capabilities[domain] = capabilities[domain] ?? {};\n capabilities[domain][action] = true;\n }\n }\n }\n return capabilities;\n}\n\nexport class Dashboard {\n private iframe: HTMLIFrameElement;\n private wrapper: HTMLDivElement;\n private overlay: HTMLElement | null = null;\n private baseUrl: string;\n private ready = false;\n private queue: Record<string, unknown>[] = [];\n private messageHandler: (e: MessageEvent) => void;\n private initialTheme?: DashboardTheme;\n private initialLang?: string;\n private initialPath: string;\n private initialTestMode?: boolean;\n private token?: string;\n private onReadyCallback?: () => void;\n private onSessionExpiredCallback?: () => void | Promise<void>;\n private events?: DashboardEvents;\n private autoHeight: boolean;\n // Overlay (modal/drawer) mode: while >0 the iframe is expanded to the full\n // viewport so the dashboard's overlay centers to the host page, not the\n // iframe. Ref-counted to survive stacked overlays.\n private overlayCount = 0;\n private savedIframeCss: string | null = null;\n private overlayRevealTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(config: DashboardConfig) {\n this.baseUrl = config.baseUrl;\n this.initialTheme = config.theme;\n this.initialLang = config.lang;\n this.initialPath = config.path ?? \"/\";\n this.initialTestMode = config.testMode;\n this.token = config.token;\n this.onReadyCallback = config.onReady;\n this.onSessionExpiredCallback = config.onSessionExpired;\n this.events = config.events;\n this.autoHeight = config.autoHeight ?? false;\n\n this.wrapper = document.createElement(\"div\");\n this.wrapper.style.position = \"relative\";\n this.wrapper.style.width = \"100%\";\n this.wrapper.style.height = \"100%\";\n\n this.iframe = document.createElement(\"iframe\");\n this.iframe.style.width = \"100%\";\n this.iframe.style.height = \"100%\";\n this.iframe.style.border = \"none\";\n this.iframe.title = \"Yuno Dashboard\";\n this.iframe.src = this.buildSrc();\n\n this.wrapper.appendChild(this.iframe);\n\n this.overlay = config.loading instanceof HTMLElement\n ? config.loading\n : this.createDefaultOverlay();\n this.overlay.style.position = \"absolute\";\n this.overlay.style.inset = \"0\";\n this.overlay.style.zIndex = \"1\";\n this.wrapper.appendChild(this.overlay);\n\n this.messageHandler = (e: MessageEvent) => {\n if (e.origin !== this.baseUrl) return;\n if (\n this.autoHeight &&\n e.data?.action === \"resize\" &&\n typeof e.data?.height === \"number\"\n ) {\n this.iframe.style.height = `${e.data.height}px`;\n this.wrapper.style.height = `${e.data.height}px`;\n return;\n }\n if (e.data?.type === \"yuno-dashboard:session-expired\") {\n this.invokeCallback(\"onSessionExpired\", () =>\n this.onSessionExpiredCallback?.(),\n );\n return;\n }\n if (e.data?.type === EMBED_EVENT_MESSAGE_TYPE) {\n this.dispatchEmbedEvent(e.data);\n return;\n }\n if (e.data?.action === \"ready\") {\n this.onReady();\n }\n if (e.data?.action === \"tokenApplied\") {\n this.onTokenApplied();\n }\n };\n window.addEventListener(\"message\", this.messageHandler);\n\n config.container.appendChild(this.wrapper);\n }\n\n setTheme(theme: DashboardTheme): void {\n if (theme.tokens || theme.typography) {\n const themePayload: Record<string, unknown> = {};\n if (theme.tokens) themePayload.colors = theme.tokens;\n if (theme.typography) themePayload.typography = theme.typography;\n this.post({ action: \"setTheme\", theme: themePayload });\n }\n if (theme.mode) {\n this.post({ action: \"setMode\", mode: theme.mode });\n }\n if (theme.styles !== undefined) {\n this.post({ action: \"setExternalStyles\", css: theme.styles });\n }\n }\n\n setLang(lang: string): void {\n this.post({ action: \"setLang\", lang });\n }\n\n setToken(token: string): void {\n this.token = token;\n this.post({ action: \"setToken\", token });\n }\n\n navigate(path: string): void {\n this.post({ action: \"navigate\", path });\n }\n\n setTestMode(enabled: boolean): void {\n this.post({ action: \"setTestMode\", testMode: enabled });\n }\n\n destroy(): void {\n window.removeEventListener(\"message\", this.messageHandler);\n this.wrapper.remove();\n this.queue = [];\n this.ready = false;\n this.overlayCount = 0;\n this.savedIframeCss = null;\n if (this.overlayRevealTimer) {\n clearTimeout(this.overlayRevealTimer);\n this.overlayRevealTimer = null;\n }\n }\n\n // Runs a host callback, swallowing sync throws and async rejections so a\n // misbehaving host handler can never break the SDK's message loop.\n private invokeCallback(\n name: string,\n run: () => void | Promise<void> | undefined,\n ): void {\n try {\n const result = run();\n if (result && typeof (result as Promise<unknown>).catch === \"function\") {\n (result as Promise<unknown>).catch((err) =>\n // eslint-disable-next-line no-console\n console.warn(`[yuno-dashboard-sdk] ${name} async callback rejected`, err),\n );\n }\n } catch (err) {\n // eslint-disable-next-line no-console\n console.warn(`[yuno-dashboard-sdk] ${name} callback threw`, err);\n }\n }\n\n // Routes an embed-event envelope to the host's events[domain][action] handler.\n private dispatchEmbedEvent(data: Record<string, unknown>): void {\n const domain = data?.domain;\n const action = data?.action;\n if (typeof domain !== \"string\" || typeof action !== \"string\") return;\n\n // UI signals are handled by the SDK itself (iframe sizing), not routed to\n // a host callback.\n if (domain === \"ui\") {\n this.handleOverlaySignal(action);\n return;\n }\n\n const groups = this.events as\n | Record<string, Record<string, EmbedEventHandler | undefined> | undefined>\n | undefined;\n const handler = groups?.[domain]?.[action];\n if (!handler) return;\n\n this.invokeCallback(`events.${domain}.${action}`, () =>\n handler({ status: data?.status, payload: data?.payload }),\n );\n }\n\n // Expands the iframe to the full viewport on the first open and restores it\n // once the last overlay closes (ref-counted for stacked overlays).\n private handleOverlaySignal(action: string): void {\n if (action === \"overlay-open\") {\n if (this.overlayCount === 0) this.expandToViewport();\n this.overlayCount += 1;\n } else if (action === \"overlay-close\") {\n if (this.overlayCount === 0) return;\n this.overlayCount -= 1;\n if (this.overlayCount === 0) this.restoreIframe();\n }\n }\n\n private expandToViewport(): void {\n // Capture where the iframe sits (its panel position) BEFORE expanding —\n // that's the offset of the host's chrome around it. The dashboard uses it\n // to leave those regions transparent so the host chrome shows through.\n const rect = this.iframe.getBoundingClientRect();\n const offset = {\n top: Math.max(0, Math.round(rect.top)),\n left: Math.max(0, Math.round(rect.left)),\n right: Math.max(0, Math.round(window.innerWidth - rect.right)),\n bottom: Math.max(0, Math.round(window.innerHeight - rect.bottom)),\n };\n\n this.savedIframeCss = this.iframe.style.cssText;\n Object.assign(this.iframe.style, {\n position: \"fixed\",\n inset: \"0\",\n width: \"100%\",\n height: \"100%\",\n zIndex: \"2147483647\",\n // Transparent so the host page shows through wherever the dashboard\n // doesn't paint (the offset regions).\n background: \"transparent\",\n // Mask the cross-document reflow: expanding the iframe and the\n // dashboard insetting its content happen a frame apart, which flickers.\n // Hide the iframe INSTANTLY (no transition here — a transition would\n // animate the hide and leave the reflow visible mid-fade) and fade it\n // back in once the inset has settled.\n transition: \"none\",\n opacity: \"0\",\n });\n this.post({ action: \"overlay-mode\", active: true, offset });\n if (this.overlayRevealTimer) clearTimeout(this.overlayRevealTimer);\n this.overlayRevealTimer = setTimeout(() => {\n this.iframe.style.transition = \"opacity 0.15s ease\";\n this.iframe.style.opacity = \"1\";\n this.overlayRevealTimer = null;\n }, 100);\n }\n\n private restoreIframe(): void {\n if (this.overlayRevealTimer) {\n clearTimeout(this.overlayRevealTimer);\n this.overlayRevealTimer = null;\n }\n // Mask the close the same way as the open: revert the geometry while the\n // iframe is hidden (instant, no transition), let the dashboard remove its\n // inset, then fade the panel back in — so the modal doesn't visibly shift\n // as the offset is removed.\n this.iframe.style.cssText = this.savedIframeCss ?? \"\";\n this.savedIframeCss = null;\n this.iframe.style.transition = \"none\";\n this.iframe.style.opacity = \"0\";\n this.post({ action: \"overlay-mode\", active: false });\n this.overlayRevealTimer = setTimeout(() => {\n this.iframe.style.transition = \"opacity 0.15s ease\";\n this.iframe.style.opacity = \"1\";\n this.overlayRevealTimer = null;\n }, 100);\n }\n\n private post(message: Record<string, unknown>): void {\n if (this.ready && this.iframe.contentWindow) {\n this.iframe.contentWindow.postMessage(message, this.baseUrl);\n } else {\n this.queue.push(message);\n }\n }\n\n private flush(): void {\n const pending = this.queue.splice(0);\n for (const message of pending) {\n if (this.iframe.contentWindow) {\n this.iframe.contentWindow.postMessage(message, this.baseUrl);\n }\n }\n }\n\n private onReady(): void {\n this.ready = true;\n const capabilities = buildCapabilities(this.events);\n if (Object.keys(capabilities).length > 0) {\n this.post({ type: HOST_CAPABILITIES_MESSAGE_TYPE, capabilities });\n }\n if (this.token) {\n this.post({ action: \"setToken\", token: this.token });\n }\n if (this.initialTheme) {\n this.setTheme(this.initialTheme);\n }\n if (this.initialLang) {\n this.setLang(this.initialLang);\n }\n this.flush();\n }\n\n private onTokenApplied(): void {\n setTimeout(() => {\n this.hideOverlay();\n this.onReadyCallback?.();\n }, 1000);\n }\n\n private hideOverlay(): void {\n if (!this.overlay) return;\n this.overlay.style.transition = \"opacity 0.3s\";\n this.overlay.style.opacity = \"0\";\n setTimeout(() => this.overlay?.remove(), 300);\n }\n\n private createDefaultOverlay(): HTMLElement {\n const overlay = document.createElement(\"div\");\n overlay.style.background = \"#ffffff\";\n overlay.style.display = \"flex\";\n overlay.style.alignItems = \"center\";\n overlay.style.justifyContent = \"center\";\n\n const spinner = document.createElement(\"div\");\n spinner.style.width = \"32px\";\n spinner.style.height = \"32px\";\n spinner.style.border = \"3px solid #e0e0e0\";\n spinner.style.borderTopColor = \"#666\";\n spinner.style.borderRadius = \"50%\";\n spinner.style.animation = \"yuno-spin 0.8s linear infinite\";\n\n const style = document.createElement(\"style\");\n style.textContent = \"@keyframes yuno-spin { to { transform: rotate(360deg); } }\";\n\n overlay.appendChild(style);\n overlay.appendChild(spinner);\n return overlay;\n }\n\n private buildSrc(): string {\n const params = new URLSearchParams({\n embed: \"true\",\n theme: this.initialTheme?.mode ?? \"light\",\n lang: this.initialLang ?? \"en\",\n });\n if (this.initialTestMode !== undefined) {\n params.set(\"test\", String(this.initialTestMode));\n }\n const path = !this.initialPath || this.initialPath === \"/\" ? \"/\" : this.initialPath;\n return `${this.baseUrl}${path}?${params.toString()}`;\n }\n}\n","import { Dashboard } from \"./dashboard\";\nimport type { DashboardConfig } from \"./types\";\n\nlet instance: Dashboard | null = null;\n\nexport function initDashboard(config: DashboardConfig): Dashboard {\n if (instance) {\n instance.destroy();\n }\n instance = new Dashboard(config);\n return instance;\n}\n\nexport function getDashboard(): Dashboard | null {\n return instance;\n}\n\nexport function destroyDashboard(): void {\n if (instance) {\n instance.destroy();\n instance = null;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/dashboard.ts","../src/singleton.ts"],"sourcesContent":["import type { DashboardTheme, DashboardConfig, DashboardEvents } from \"./types\";\n\nconst EMBED_EVENT_MESSAGE_TYPE = \"yuno-dashboard:embed-event\";\nconst HOST_CAPABILITIES_MESSAGE_TYPE = \"yuno-dashboard:host-capabilities\";\n\ntype EmbedEventHandler = (event: {\n status?: unknown;\n payload?: unknown;\n}) => void | Promise<void>;\n\n// Build the capability map the dashboard reads to decide which actions the\n// host owns: { connections: { created: true }, ... } for every provided handler.\nfunction buildCapabilities(\n events?: DashboardEvents,\n): Record<string, Record<string, boolean>> {\n const capabilities: Record<string, Record<string, boolean>> = {};\n if (!events) return capabilities;\n const groups = events as Record<string, Record<string, unknown> | undefined>;\n for (const domain of Object.keys(groups)) {\n const group = groups[domain];\n if (!group) continue;\n for (const action of Object.keys(group)) {\n if (typeof group[action] === \"function\") {\n capabilities[domain] = capabilities[domain] ?? {};\n capabilities[domain][action] = true;\n }\n }\n }\n return capabilities;\n}\n\nexport class Dashboard {\n private iframe: HTMLIFrameElement;\n private wrapper: HTMLDivElement;\n private overlay: HTMLElement | null = null;\n private baseUrl: string;\n private ready = false;\n private queue: Record<string, unknown>[] = [];\n private messageHandler: (e: MessageEvent) => void;\n private initialTheme?: DashboardTheme;\n private initialLang?: string;\n private initialPath: string;\n private initialTestMode?: boolean;\n private token?: string;\n private onReadyCallback?: () => void;\n private onSessionExpiredCallback?: () => void | Promise<void>;\n private events?: DashboardEvents;\n private autoHeight: boolean;\n // Overlay (modal/drawer) mode: while >0 the iframe is expanded to the full\n // viewport so the dashboard's overlay centers to the host page, not the\n // iframe. Ref-counted to survive stacked overlays.\n private overlayCount = 0;\n private savedIframeCss: string | null = null;\n\n constructor(config: DashboardConfig) {\n this.baseUrl = config.baseUrl;\n this.initialTheme = config.theme;\n this.initialLang = config.lang;\n this.initialPath = config.path ?? \"/\";\n this.initialTestMode = config.testMode;\n this.token = config.token;\n this.onReadyCallback = config.onReady;\n this.onSessionExpiredCallback = config.onSessionExpired;\n this.events = config.events;\n this.autoHeight = config.autoHeight ?? false;\n\n this.wrapper = document.createElement(\"div\");\n this.wrapper.style.position = \"relative\";\n this.wrapper.style.width = \"100%\";\n this.wrapper.style.height = \"100%\";\n\n this.iframe = document.createElement(\"iframe\");\n this.iframe.style.width = \"100%\";\n this.iframe.style.height = \"100%\";\n this.iframe.style.border = \"none\";\n this.iframe.title = \"Yuno Dashboard\";\n this.iframe.src = this.buildSrc();\n\n this.wrapper.appendChild(this.iframe);\n\n this.overlay = config.loading instanceof HTMLElement\n ? config.loading\n : this.createDefaultOverlay();\n this.overlay.style.position = \"absolute\";\n this.overlay.style.inset = \"0\";\n this.overlay.style.zIndex = \"1\";\n this.wrapper.appendChild(this.overlay);\n\n this.messageHandler = (e: MessageEvent) => {\n if (e.origin !== this.baseUrl) return;\n if (\n this.autoHeight &&\n e.data?.action === \"resize\" &&\n typeof e.data?.height === \"number\"\n ) {\n this.iframe.style.height = `${e.data.height}px`;\n this.wrapper.style.height = `${e.data.height}px`;\n return;\n }\n if (e.data?.type === \"yuno-dashboard:session-expired\") {\n this.invokeCallback(\"onSessionExpired\", () =>\n this.onSessionExpiredCallback?.(),\n );\n return;\n }\n if (e.data?.type === EMBED_EVENT_MESSAGE_TYPE) {\n this.dispatchEmbedEvent(e.data);\n return;\n }\n if (e.data?.action === \"ready\") {\n this.onReady();\n }\n if (e.data?.action === \"tokenApplied\") {\n this.onTokenApplied();\n }\n };\n window.addEventListener(\"message\", this.messageHandler);\n\n config.container.appendChild(this.wrapper);\n }\n\n setTheme(theme: DashboardTheme): void {\n if (theme.tokens || theme.typography) {\n const themePayload: Record<string, unknown> = {};\n if (theme.tokens) themePayload.colors = theme.tokens;\n if (theme.typography) themePayload.typography = theme.typography;\n this.post({ action: \"setTheme\", theme: themePayload });\n }\n if (theme.mode) {\n this.post({ action: \"setMode\", mode: theme.mode });\n }\n if (theme.styles !== undefined) {\n this.post({ action: \"setExternalStyles\", css: theme.styles });\n }\n }\n\n setLang(lang: string): void {\n this.post({ action: \"setLang\", lang });\n }\n\n setToken(token: string): void {\n this.token = token;\n this.post({ action: \"setToken\", token });\n }\n\n navigate(path: string): void {\n this.post({ action: \"navigate\", path });\n }\n\n setTestMode(enabled: boolean): void {\n this.post({ action: \"setTestMode\", testMode: enabled });\n }\n\n destroy(): void {\n window.removeEventListener(\"message\", this.messageHandler);\n this.wrapper.remove();\n this.queue = [];\n this.ready = false;\n this.overlayCount = 0;\n this.savedIframeCss = null;\n }\n\n // Runs a host callback, swallowing sync throws and async rejections so a\n // misbehaving host handler can never break the SDK's message loop.\n private invokeCallback(\n name: string,\n run: () => void | Promise<void> | undefined,\n ): void {\n try {\n const result = run();\n if (result && typeof (result as Promise<unknown>).catch === \"function\") {\n (result as Promise<unknown>).catch((err) =>\n // eslint-disable-next-line no-console\n console.warn(`[yuno-dashboard-sdk] ${name} async callback rejected`, err),\n );\n }\n } catch (err) {\n // eslint-disable-next-line no-console\n console.warn(`[yuno-dashboard-sdk] ${name} callback threw`, err);\n }\n }\n\n // Routes an embed-event envelope to the host's events[domain][action] handler.\n private dispatchEmbedEvent(data: Record<string, unknown>): void {\n const domain = data?.domain;\n const action = data?.action;\n if (typeof domain !== \"string\" || typeof action !== \"string\") return;\n\n // UI signals are handled by the SDK itself (iframe sizing), not routed to\n // a host callback.\n if (domain === \"ui\") {\n this.handleOverlaySignal(action);\n return;\n }\n\n const groups = this.events as\n | Record<string, Record<string, EmbedEventHandler | undefined> | undefined>\n | undefined;\n const handler = groups?.[domain]?.[action];\n if (!handler) return;\n\n this.invokeCallback(`events.${domain}.${action}`, () =>\n handler({ status: data?.status, payload: data?.payload }),\n );\n }\n\n // Expands the iframe to the full viewport on the first open and restores it\n // once the last overlay closes (ref-counted for stacked overlays).\n private handleOverlaySignal(action: string): void {\n if (action === \"overlay-open\") {\n if (this.overlayCount === 0) this.expandToViewport();\n this.overlayCount += 1;\n } else if (action === \"overlay-close\") {\n if (this.overlayCount === 0) return;\n this.overlayCount -= 1;\n if (this.overlayCount === 0) this.restoreIframe();\n }\n }\n\n private expandToViewport(): void {\n // Capture where the iframe sits (its panel position) BEFORE expanding —\n // that's the offset of the host's chrome around it. The dashboard uses it\n // to leave those regions transparent so the host chrome shows through.\n const rect = this.iframe.getBoundingClientRect();\n const offset = {\n top: Math.max(0, Math.round(rect.top)),\n left: Math.max(0, Math.round(rect.left)),\n right: Math.max(0, Math.round(window.innerWidth - rect.right)),\n bottom: Math.max(0, Math.round(window.innerHeight - rect.bottom)),\n };\n\n this.savedIframeCss = this.iframe.style.cssText;\n Object.assign(this.iframe.style, {\n position: \"fixed\",\n inset: \"0\",\n width: \"100%\",\n height: \"100%\",\n zIndex: \"2147483647\",\n // Transparent so the host page shows through wherever the dashboard\n // doesn't paint (the offset regions).\n background: \"transparent\",\n });\n this.post({ action: \"overlay-mode\", active: true, offset });\n }\n\n private restoreIframe(): void {\n this.iframe.style.cssText = this.savedIframeCss ?? \"\";\n this.savedIframeCss = null;\n this.post({ action: \"overlay-mode\", active: false });\n }\n\n private post(message: Record<string, unknown>): void {\n if (this.ready && this.iframe.contentWindow) {\n this.iframe.contentWindow.postMessage(message, this.baseUrl);\n } else {\n this.queue.push(message);\n }\n }\n\n private flush(): void {\n const pending = this.queue.splice(0);\n for (const message of pending) {\n if (this.iframe.contentWindow) {\n this.iframe.contentWindow.postMessage(message, this.baseUrl);\n }\n }\n }\n\n private onReady(): void {\n this.ready = true;\n const capabilities = buildCapabilities(this.events);\n if (Object.keys(capabilities).length > 0) {\n this.post({ type: HOST_CAPABILITIES_MESSAGE_TYPE, capabilities });\n }\n if (this.token) {\n this.post({ action: \"setToken\", token: this.token });\n }\n if (this.initialTheme) {\n this.setTheme(this.initialTheme);\n }\n if (this.initialLang) {\n this.setLang(this.initialLang);\n }\n this.flush();\n }\n\n private onTokenApplied(): void {\n setTimeout(() => {\n this.hideOverlay();\n this.onReadyCallback?.();\n }, 1000);\n }\n\n private hideOverlay(): void {\n if (!this.overlay) return;\n this.overlay.style.transition = \"opacity 0.3s\";\n this.overlay.style.opacity = \"0\";\n setTimeout(() => this.overlay?.remove(), 300);\n }\n\n private createDefaultOverlay(): HTMLElement {\n const overlay = document.createElement(\"div\");\n overlay.style.background = \"#ffffff\";\n overlay.style.display = \"flex\";\n overlay.style.alignItems = \"center\";\n overlay.style.justifyContent = \"center\";\n\n const spinner = document.createElement(\"div\");\n spinner.style.width = \"32px\";\n spinner.style.height = \"32px\";\n spinner.style.border = \"3px solid #e0e0e0\";\n spinner.style.borderTopColor = \"#666\";\n spinner.style.borderRadius = \"50%\";\n spinner.style.animation = \"yuno-spin 0.8s linear infinite\";\n\n const style = document.createElement(\"style\");\n style.textContent = \"@keyframes yuno-spin { to { transform: rotate(360deg); } }\";\n\n overlay.appendChild(style);\n overlay.appendChild(spinner);\n return overlay;\n }\n\n private buildSrc(): string {\n const params = new URLSearchParams({\n embed: \"true\",\n theme: this.initialTheme?.mode ?? \"light\",\n lang: this.initialLang ?? \"en\",\n });\n if (this.initialTestMode !== undefined) {\n params.set(\"test\", String(this.initialTestMode));\n }\n const path = !this.initialPath || this.initialPath === \"/\" ? \"/\" : this.initialPath;\n return `${this.baseUrl}${path}?${params.toString()}`;\n }\n}\n","import { Dashboard } from \"./dashboard\";\nimport type { DashboardConfig } from \"./types\";\n\nlet instance: Dashboard | null = null;\n\nexport function initDashboard(config: DashboardConfig): Dashboard {\n if (instance) {\n instance.destroy();\n }\n instance = new Dashboard(config);\n return instance;\n}\n\nexport function getDashboard(): Dashboard | null {\n return instance;\n}\n\nexport function destroyDashboard(): void {\n if (instance) {\n instance.destroy();\n instance = null;\n }\n}\n"],"mappings":"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","names":[]}
|