@yuno-payments/dashboard-embed-sdk 0.2.7 → 0.3.0-beta.1
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/README.md +90 -19
- package/dist/index.d.ts +7 -3
- package/dist/index.js +6 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,60 +8,131 @@ Lightweight SDK for embedding the Yuno Dashboard via iframe. Zero dependencies
|
|
|
8
8
|
npm install @yuno-payments/dashboard-embed-sdk
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Quick Start
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
import {
|
|
14
|
+
import { initYunoDashboard } from "@yuno-payments/dashboard-embed-sdk";
|
|
15
15
|
|
|
16
|
-
const sdk =
|
|
16
|
+
const sdk = initYunoDashboard({
|
|
17
17
|
baseUrl: "https://dashboard.y.uno",
|
|
18
18
|
container: document.getElementById("dashboard")!,
|
|
19
19
|
token: "your-jwt-token",
|
|
20
20
|
theme: {
|
|
21
|
+
// Simple: flat tokens apply to light mode; dark mode uses design system defaults
|
|
21
22
|
tokens: { primary: "#134AC3" },
|
|
22
|
-
|
|
23
|
+
// Per-mode: full control over both light and dark colors
|
|
24
|
+
// tokens: {
|
|
25
|
+
// light: { primary: "#134AC3", background: "#FFFFFF" },
|
|
26
|
+
// dark: { primary: "#5B7BFF", background: "#0A0A0A" },
|
|
27
|
+
// },
|
|
28
|
+
typography: {
|
|
29
|
+
fontFamily: "'Inter', sans-serif",
|
|
30
|
+
fontUrl: "https://fonts.googleapis.com/css2?family=Inter",
|
|
31
|
+
},
|
|
23
32
|
mode: "light",
|
|
24
33
|
styles: ".yuno-card { border-radius: 8px; }",
|
|
25
34
|
},
|
|
26
35
|
lang: "en",
|
|
36
|
+
path: "/connections",
|
|
37
|
+
onReady: () => console.log("Dashboard is ready"),
|
|
27
38
|
});
|
|
39
|
+
```
|
|
28
40
|
|
|
29
|
-
|
|
30
|
-
sdk.navigate("/connections");
|
|
41
|
+
## API
|
|
31
42
|
|
|
32
|
-
|
|
33
|
-
sdk.setTheme({ tokens: { primary: "#FF0000" } });
|
|
43
|
+
### Singleton helpers
|
|
34
44
|
|
|
35
|
-
|
|
36
|
-
sdk.setLang("es");
|
|
45
|
+
The recommended way to manage the SDK instance:
|
|
37
46
|
|
|
38
|
-
|
|
39
|
-
|
|
47
|
+
```ts
|
|
48
|
+
import {
|
|
49
|
+
initYunoDashboard,
|
|
50
|
+
getYunoDashboard,
|
|
51
|
+
destroyYunoDashboard,
|
|
52
|
+
} from "@yuno-payments/dashboard-embed-sdk";
|
|
40
53
|
|
|
41
|
-
//
|
|
42
|
-
sdk
|
|
43
|
-
```
|
|
54
|
+
// Create (destroys any previous instance automatically)
|
|
55
|
+
const sdk = initYunoDashboard(config);
|
|
44
56
|
|
|
45
|
-
|
|
57
|
+
// Retrieve the current instance from anywhere
|
|
58
|
+
const sdk = getYunoDashboard();
|
|
59
|
+
|
|
60
|
+
// Destroy the instance and clean up
|
|
61
|
+
destroyYunoDashboard();
|
|
62
|
+
```
|
|
46
63
|
|
|
47
|
-
### `new YunoDashboard(config)`
|
|
64
|
+
### `new YunoDashboard(config)` / `initYunoDashboard(config)`
|
|
48
65
|
|
|
49
66
|
| Option | Type | Required | Description |
|
|
50
67
|
|---|---|---|---|
|
|
51
68
|
| `baseUrl` | `string` | Yes | Dashboard base URL |
|
|
52
69
|
| `container` | `HTMLElement` | Yes | Element to mount the iframe |
|
|
53
|
-
| `token` | `string` | No | JWT auth token |
|
|
70
|
+
| `token` | `string` | No | JWT auth token — sent via PostMessage after the iframe is ready |
|
|
54
71
|
| `theme` | `DashboardTheme` | No | Initial theme configuration |
|
|
55
72
|
| `lang` | `string` | No | Language code (default: `"en"`) |
|
|
73
|
+
| `path` | `string` | No | Initial navigation path (default: `"/"`) |
|
|
74
|
+
| `onReady` | `() => void` | No | Callback invoked when the dashboard is fully loaded and authenticated |
|
|
75
|
+
| `loading` | `HTMLElement` | No | Custom loading overlay element. If omitted, a default spinner is shown |
|
|
56
76
|
|
|
57
77
|
### Methods
|
|
58
78
|
|
|
59
79
|
- **`setTheme(theme)`** — Update colors, typography, mode, or external styles
|
|
60
80
|
- **`setLang(lang)`** — Change display language
|
|
61
|
-
- **`setToken(token)`** —
|
|
81
|
+
- **`setToken(token)`** — Update the auth token via PostMessage
|
|
62
82
|
- **`navigate(path)`** — Navigate to a dashboard route
|
|
63
83
|
- **`destroy()`** — Remove iframe and clean up event listeners
|
|
64
84
|
|
|
85
|
+
### Types
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
interface ThemeColors {
|
|
89
|
+
primary: string;
|
|
90
|
+
primaryForeground: string;
|
|
91
|
+
secondary: string;
|
|
92
|
+
secondaryForeground: string;
|
|
93
|
+
background: string;
|
|
94
|
+
foreground: string;
|
|
95
|
+
muted: string;
|
|
96
|
+
mutedForeground: string;
|
|
97
|
+
accent: string;
|
|
98
|
+
accentForeground: string;
|
|
99
|
+
destructive: string;
|
|
100
|
+
destructiveForeground: string;
|
|
101
|
+
border: string;
|
|
102
|
+
input: string;
|
|
103
|
+
ring: string;
|
|
104
|
+
surface: string;
|
|
105
|
+
card: string;
|
|
106
|
+
cardForeground: string;
|
|
107
|
+
popover: string;
|
|
108
|
+
popoverForeground: string;
|
|
109
|
+
success: string;
|
|
110
|
+
warning: string;
|
|
111
|
+
info: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
interface ThemeTypography {
|
|
115
|
+
fontFamily: string;
|
|
116
|
+
fontUrl: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
interface ModeTokens {
|
|
120
|
+
light?: Partial<ThemeColors>;
|
|
121
|
+
dark?: Partial<ThemeColors>;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
interface DashboardTheme {
|
|
125
|
+
tokens?: Partial<ThemeColors> | ModeTokens; // flat OR per-mode
|
|
126
|
+
typography?: Partial<ThemeTypography>;
|
|
127
|
+
mode?: "light" | "dark";
|
|
128
|
+
styles?: string; // Custom CSS injected into the dashboard
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Loading overlay
|
|
133
|
+
|
|
134
|
+
A loading overlay covers the iframe while initialization completes. You can provide a custom element via the `loading` config option, or the SDK renders a default spinner. The overlay fades out automatically (300ms transition) once the dashboard is authenticated and ready.
|
|
135
|
+
|
|
65
136
|
## Development
|
|
66
137
|
|
|
67
138
|
```bash
|
package/dist/index.d.ts
CHANGED
|
@@ -27,8 +27,12 @@ interface ThemeTypography {
|
|
|
27
27
|
fontFamily: string;
|
|
28
28
|
fontUrl: string;
|
|
29
29
|
}
|
|
30
|
+
interface ModeTokens {
|
|
31
|
+
light?: Partial<ThemeColors>;
|
|
32
|
+
dark?: Partial<ThemeColors>;
|
|
33
|
+
}
|
|
30
34
|
interface DashboardTheme {
|
|
31
|
-
tokens?: Partial<ThemeColors
|
|
35
|
+
tokens?: Partial<ThemeColors> | ModeTokens;
|
|
32
36
|
typography?: Partial<ThemeTypography>;
|
|
33
37
|
mode?: "light" | "dark";
|
|
34
38
|
styles?: string;
|
|
@@ -41,7 +45,7 @@ interface YunoDashboardConfig {
|
|
|
41
45
|
lang?: string;
|
|
42
46
|
path?: string;
|
|
43
47
|
onReady?: () => void;
|
|
44
|
-
loading?:
|
|
48
|
+
loading?: HTMLElement;
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
declare class YunoDashboard {
|
|
@@ -76,4 +80,4 @@ declare function initYunoDashboard(config: YunoDashboardConfig): YunoDashboard;
|
|
|
76
80
|
declare function getYunoDashboard(): YunoDashboard | null;
|
|
77
81
|
declare function destroyYunoDashboard(): void;
|
|
78
82
|
|
|
79
|
-
export { type DashboardTheme, type ThemeColors, type ThemeTypography, YunoDashboard, type YunoDashboardConfig, destroyYunoDashboard, getYunoDashboard, initYunoDashboard };
|
|
83
|
+
export { type DashboardTheme, type ModeTokens, type ThemeColors, type ThemeTypography, YunoDashboard, type YunoDashboardConfig, destroyYunoDashboard, getYunoDashboard, initYunoDashboard };
|
package/dist/index.js
CHANGED
|
@@ -21,17 +21,11 @@ var YunoDashboard = class {
|
|
|
21
21
|
this.iframe.title = "Yuno Dashboard";
|
|
22
22
|
this.iframe.src = this.buildSrc();
|
|
23
23
|
this.wrapper.appendChild(this.iframe);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
this.overlay.style.position = "absolute";
|
|
31
|
-
this.overlay.style.inset = "0";
|
|
32
|
-
this.overlay.style.zIndex = "1";
|
|
33
|
-
this.wrapper.appendChild(this.overlay);
|
|
34
|
-
}
|
|
24
|
+
this.overlay = config.loading instanceof HTMLElement ? config.loading : this.createDefaultOverlay();
|
|
25
|
+
this.overlay.style.position = "absolute";
|
|
26
|
+
this.overlay.style.inset = "0";
|
|
27
|
+
this.overlay.style.zIndex = "1";
|
|
28
|
+
this.wrapper.appendChild(this.overlay);
|
|
35
29
|
this.messageHandler = (e) => {
|
|
36
30
|
if (e.origin !== this.baseUrl) return;
|
|
37
31
|
if (e.data?.action === "ready") {
|
|
@@ -139,7 +133,7 @@ var YunoDashboard = class {
|
|
|
139
133
|
buildSrc() {
|
|
140
134
|
const params = new URLSearchParams({
|
|
141
135
|
embed: "true",
|
|
142
|
-
theme: "light",
|
|
136
|
+
theme: this.initialTheme?.mode ?? "light",
|
|
143
137
|
lang: this.initialLang ?? "en"
|
|
144
138
|
});
|
|
145
139
|
return `${this.baseUrl}/?${params.toString()}`;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/yuno-dashboard.ts","../src/singleton.ts"],"sourcesContent":["import type { DashboardTheme, YunoDashboardConfig } from \"./types\";\n\nexport class YunoDashboard {\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 token?: string;\n private onReadyCallback?: () => void;\n\n constructor(config: YunoDashboardConfig) {\n this.baseUrl = config.baseUrl;\n this.initialTheme = config.theme;\n this.initialLang = config.lang;\n this.initialPath = config.path ?? \"/\";\n this.token = config.token;\n this.onReadyCallback = config.onReady;\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
|
|
1
|
+
{"version":3,"sources":["../src/yuno-dashboard.ts","../src/singleton.ts"],"sourcesContent":["import type { DashboardTheme, YunoDashboardConfig } from \"./types\";\n\nexport class YunoDashboard {\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 token?: string;\n private onReadyCallback?: () => void;\n\n constructor(config: YunoDashboardConfig) {\n this.baseUrl = config.baseUrl;\n this.initialTheme = config.theme;\n this.initialLang = config.lang;\n this.initialPath = config.path ?? \"/\";\n this.token = config.token;\n this.onReadyCallback = config.onReady;\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 (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 destroy(): void {\n window.removeEventListener(\"message\", this.messageHandler);\n this.wrapper.remove();\n this.queue = [];\n this.ready = 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 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 if (this.initialPath !== \"/\") {\n this.post({ action: \"navigate\", path: this.initialPath });\n }\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 return `${this.baseUrl}/?${params.toString()}`;\n }\n}\n","import { YunoDashboard } from \"./yuno-dashboard\";\nimport type { YunoDashboardConfig } from \"./types\";\n\nlet instance: YunoDashboard | null = null;\n\nexport function initYunoDashboard(config: YunoDashboardConfig): YunoDashboard {\n if (instance) {\n instance.destroy();\n }\n instance = new YunoDashboard(config);\n return instance;\n}\n\nexport function getYunoDashboard(): YunoDashboard | null {\n return instance;\n}\n\nexport function destroyYunoDashboard(): void {\n if (instance) {\n instance.destroy();\n instance = null;\n }\n}\n"],"mappings":"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","names":[]}
|