@salla.sa/embedded-sdk 0.1.0-beta.5 → 0.1.0-beta.6
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 +38 -253
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +10 -8
- package/dist/esm/index.js.map +1 -1
- package/dist/system/index.js +2 -2
- package/dist/system/index.js.map +1 -1
- package/dist/umd/index.js +2 -2
- package/dist/umd/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,295 +14,80 @@ yarn add @salla.sa/embedded-sdk
|
|
|
14
14
|
|
|
15
15
|
## Quick Start
|
|
16
16
|
|
|
17
|
-
### ES Modules (Recommended)
|
|
18
|
-
|
|
19
17
|
```typescript
|
|
20
18
|
import { embedded } from "@salla.sa/embedded-sdk";
|
|
21
19
|
|
|
22
20
|
async function bootstrap() {
|
|
23
21
|
try {
|
|
24
|
-
//
|
|
22
|
+
// Initialize SDK
|
|
25
23
|
const { layout } = await embedded.init({ debug: true });
|
|
26
|
-
console.log("Theme:", layout.theme);
|
|
27
|
-
console.log("Locale:", layout.locale);
|
|
28
24
|
|
|
29
|
-
//
|
|
25
|
+
// Get token
|
|
30
26
|
const token = embedded.auth.getToken();
|
|
31
|
-
if (!token)
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
if (!token) throw new Error("No token found");
|
|
28
|
+
|
|
29
|
+
// Verify token with your backend before signaling ready
|
|
30
|
+
const isValid = await fetch("/api/verify-token", {
|
|
31
|
+
method: "POST",
|
|
32
|
+
headers: { "Content-Type": "application/json" },
|
|
33
|
+
body: JSON.stringify({ token }),
|
|
34
|
+
}).then((res) => res.ok);
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
if (!verified) {
|
|
37
|
-
throw new Error("Token verification failed");
|
|
38
|
-
}
|
|
36
|
+
if (!isValid) throw new Error("Token is invalid");
|
|
39
37
|
|
|
40
|
-
//
|
|
38
|
+
// Signal app is ready only after successful verification
|
|
41
39
|
embedded.ready();
|
|
42
40
|
|
|
43
|
-
//
|
|
41
|
+
// Set up your app
|
|
44
42
|
embedded.page.setTitle("My App");
|
|
45
43
|
} catch (err) {
|
|
46
|
-
// Exit embedded view (navigates to apps page)
|
|
47
44
|
embedded.destroy();
|
|
48
45
|
}
|
|
49
46
|
}
|
|
50
|
-
|
|
51
|
-
bootstrap();
|
|
52
47
|
```
|
|
53
48
|
|
|
54
|
-
|
|
49
|
+
– End of Selection
|
|
55
50
|
|
|
56
|
-
```html
|
|
57
|
-
<script src="https://unpkg.com/@salla.sa/embedded-sdk/dist/index.umd.js"></script>
|
|
58
|
-
<script>
|
|
59
|
-
const embedded = SallaEmbeddedSDK.embedded;
|
|
60
|
-
|
|
61
|
-
embedded.init({ debug: true }).then(function (result) {
|
|
62
|
-
console.log("Layout:", result.layout);
|
|
63
|
-
|
|
64
|
-
const token = embedded.auth.getToken();
|
|
65
|
-
// ... verify token and call embedded.ready()
|
|
66
|
-
});
|
|
67
|
-
</script>
|
|
68
51
|
```
|
|
69
52
|
|
|
70
|
-
|
|
53
|
+
bootstrap();
|
|
54
|
+
```
|
|
71
55
|
|
|
72
|
-
|
|
56
|
+
### Browser Global
|
|
73
57
|
|
|
74
58
|
```html
|
|
59
|
+
<script src="https://unpkg.com/@salla.sa/embedded-sdk/dist/umd/index.js"></script>
|
|
75
60
|
<script>
|
|
76
|
-
|
|
77
|
-
|
|
61
|
+
const embedded = Salla.embedded;
|
|
62
|
+
embedded.init({ debug: true }).then((result) => {
|
|
63
|
+
console.log("Layout:", result.layout);
|
|
64
|
+
embedded.ready();
|
|
65
|
+
});
|
|
78
66
|
</script>
|
|
79
67
|
```
|
|
80
68
|
|
|
81
69
|
## API Overview
|
|
82
70
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
```typescript
|
|
86
|
-
const { layout } = await embedded.init({
|
|
87
|
-
debug: false, // Optional: Enable debug logging
|
|
88
|
-
});
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
Returns layout information from the host:
|
|
92
|
-
|
|
93
|
-
```typescript
|
|
94
|
-
interface LayoutInfo {
|
|
95
|
-
theme: "light" | "dark";
|
|
96
|
-
width: number;
|
|
97
|
-
locale: string;
|
|
98
|
-
currency: string;
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Core Methods
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
// Signal app is ready (removes host loading overlay)
|
|
106
|
-
embedded.ready();
|
|
107
|
-
|
|
108
|
-
// Get current state
|
|
109
|
-
const state = embedded.getState();
|
|
110
|
-
|
|
111
|
-
// Check if initialized
|
|
112
|
-
const ready = embedded.isReady();
|
|
113
|
-
|
|
114
|
-
// Subscribe to initialization
|
|
115
|
-
embedded.onInit((state) => {
|
|
116
|
-
console.log("Initialized with layout:", state.layout);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// Send log message to host
|
|
120
|
-
embedded.log("error", "Something failed", { context: "data" });
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### Auth Module
|
|
124
|
-
|
|
125
|
-
```typescript
|
|
126
|
-
// Get token from URL (?token=XXX)
|
|
127
|
-
const token = embedded.auth.getToken();
|
|
128
|
-
|
|
129
|
-
// Request token refresh (re-renders iframe with new token)
|
|
130
|
-
embedded.auth.refresh();
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Destroy
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
// Exit embedded view and navigate back to app page
|
|
137
|
-
embedded.destroy();
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### UI Module
|
|
141
|
-
|
|
142
|
-
```typescript
|
|
143
|
-
// Loading (in-app loading states)
|
|
144
|
-
embedded.ui.loading.show(); // Show loading
|
|
145
|
-
embedded.ui.loading.show("component"); // Component-level
|
|
146
|
-
embedded.ui.loading.hide(); // Hide loading
|
|
147
|
-
|
|
148
|
-
// Toast Notifications
|
|
149
|
-
embedded.ui.toast.success("Product saved!");
|
|
150
|
-
embedded.ui.toast.error("Something went wrong");
|
|
151
|
-
embedded.ui.toast.warning("Please review input");
|
|
152
|
-
embedded.ui.toast.info("New features available");
|
|
153
|
-
embedded.ui.toast.success("Saved!", 5000); // Custom duration
|
|
154
|
-
|
|
155
|
-
// Generic toast
|
|
156
|
-
embedded.ui.toast.show({
|
|
157
|
-
type: "success",
|
|
158
|
-
message: "Done!",
|
|
159
|
-
duration: 3000,
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
// Modal
|
|
163
|
-
embedded.ui.modal.open("my-modal", { data: 123 });
|
|
164
|
-
embedded.ui.modal.close("my-modal");
|
|
165
|
-
|
|
166
|
-
// Confirm Dialog (async)
|
|
167
|
-
const result = await embedded.ui.confirm({
|
|
168
|
-
title: "Delete Product?",
|
|
169
|
-
message: "This action cannot be undone.",
|
|
170
|
-
confirmText: "Delete",
|
|
171
|
-
cancelText: "Cancel",
|
|
172
|
-
variant: "danger", // 'danger' | 'warning' | 'info'
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
if (result.confirmed) {
|
|
176
|
-
await deleteProduct();
|
|
177
|
-
}
|
|
178
|
-
```
|
|
71
|
+
The SDK provides modules for authentication, UI components, navigation, and page management:
|
|
179
72
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
embedded.page.setTitle("Product Details");
|
|
185
|
-
|
|
186
|
-
// SPA Navigation (React Router)
|
|
187
|
-
embedded.page.navigate("/products");
|
|
188
|
-
embedded.page.navigate("/orders", { replace: true });
|
|
189
|
-
embedded.page.navigate("/item", { state: { id: 123 } });
|
|
190
|
-
|
|
191
|
-
// Full Page Redirect
|
|
192
|
-
embedded.page.redirect("https://external-site.com");
|
|
193
|
-
|
|
194
|
-
// Auto-detect (internal → navigate, external → redirect)
|
|
195
|
-
embedded.page.navTo("/products");
|
|
196
|
-
embedded.page.navTo("https://external.com");
|
|
197
|
-
|
|
198
|
-
// Iframe Resize
|
|
199
|
-
embedded.page.resize(800);
|
|
200
|
-
embedded.page.autoResize(); // Auto-detect content height
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
### Nav Module
|
|
204
|
-
|
|
205
|
-
```typescript
|
|
206
|
-
// Set primary action button with onClick
|
|
207
|
-
embedded.nav.setAction({
|
|
208
|
-
title: "Create Product",
|
|
209
|
-
onClick: () => {
|
|
210
|
-
// Handle click
|
|
211
|
-
console.log("Create product clicked");
|
|
212
|
-
},
|
|
213
|
-
});
|
|
73
|
+
- **Auth**: `getToken()`, `getAppId()`, `refresh()`, `introspect()`
|
|
74
|
+
- **UI**: `loading`, `toast`, `modal`, `confirm`
|
|
75
|
+
- **Page**: `setTitle()`, `navigate()`, `redirect()`, `resize()`
|
|
76
|
+
- **Nav**: `setAction()`, `onActionClick()`, `clearAction()`
|
|
214
77
|
|
|
215
|
-
|
|
216
|
-
embedded.nav.setAction({
|
|
217
|
-
title: "Save",
|
|
218
|
-
subTitle: "Save changes",
|
|
219
|
-
icon: "sicon-save",
|
|
220
|
-
disabled: false,
|
|
221
|
-
onClick: () => {
|
|
222
|
-
handleSave();
|
|
223
|
-
},
|
|
224
|
-
});
|
|
78
|
+
## TypeScript
|
|
225
79
|
|
|
226
|
-
|
|
227
|
-
embedded.nav.setAction({
|
|
228
|
-
title: "Actions",
|
|
229
|
-
value: "main",
|
|
230
|
-
onClick: () => {
|
|
231
|
-
// Handle main action click
|
|
232
|
-
},
|
|
233
|
-
extendedActions: [
|
|
234
|
-
{ title: "Import", url: "/import" },
|
|
235
|
-
{ title: "Export", value: "export" },
|
|
236
|
-
],
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
// Listen for action clicks
|
|
240
|
-
const unsubscribe = embedded.nav.onActionClick((url, value) => {
|
|
241
|
-
if (value === "export") {
|
|
242
|
-
handleExport();
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
// Clear action button
|
|
247
|
-
embedded.nav.clearAction();
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
### Checkout Module
|
|
251
|
-
|
|
252
|
-
```typescript
|
|
253
|
-
embedded.checkout.create({
|
|
254
|
-
items: [{ productId: 123, quantity: 1 }],
|
|
255
|
-
amount: 99.99,
|
|
256
|
-
currency: "SAR",
|
|
257
|
-
});
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
### Theme Support
|
|
261
|
-
|
|
262
|
-
```typescript
|
|
263
|
-
// Get current theme from state
|
|
264
|
-
const theme = embedded.getState().layout.theme;
|
|
265
|
-
|
|
266
|
-
// Listen for theme changes
|
|
267
|
-
const unsubscribe = embedded.onThemeChange((theme) => {
|
|
268
|
-
document.body.classList.toggle("dark", theme === "dark");
|
|
269
|
-
});
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
## TypeScript Support
|
|
273
|
-
|
|
274
|
-
Full TypeScript support with exported types:
|
|
275
|
-
|
|
276
|
-
```typescript
|
|
277
|
-
import type {
|
|
278
|
-
EmbeddedState,
|
|
279
|
-
LayoutInfo,
|
|
280
|
-
InitOptions,
|
|
281
|
-
ToastOptions,
|
|
282
|
-
ToastType,
|
|
283
|
-
ConfirmOptions,
|
|
284
|
-
ConfirmResult,
|
|
285
|
-
PrimaryActionConfig,
|
|
286
|
-
ExtendedAction,
|
|
287
|
-
CheckoutPayload,
|
|
288
|
-
} from "@salla.sa/embedded-sdk";
|
|
289
|
-
```
|
|
80
|
+
Full TypeScript support with exported types. See [documentation](#) for complete type reference.
|
|
290
81
|
|
|
291
82
|
## Build Formats
|
|
292
83
|
|
|
293
|
-
| Format | File |
|
|
294
|
-
| -------- | ---------------------- |
|
|
295
|
-
| ESM | `dist/index.
|
|
296
|
-
| CommonJS | `dist/index.
|
|
297
|
-
| UMD | `dist/index.
|
|
298
|
-
| SystemJS | `dist/index.
|
|
84
|
+
| Format | File |
|
|
85
|
+
| -------- | ---------------------- |
|
|
86
|
+
| ESM | `dist/esm/index.js` |
|
|
87
|
+
| CommonJS | `dist/cjs/index.js` |
|
|
88
|
+
| UMD | `dist/umd/index.js` |
|
|
89
|
+
| SystemJS | `dist/system/index.js` |
|
|
299
90
|
|
|
300
|
-
##
|
|
91
|
+
## Documentation
|
|
301
92
|
|
|
302
|
-
|
|
303
|
-
pnpm install # Install dependencies
|
|
304
|
-
pnpm dev # Development build with watch
|
|
305
|
-
pnpm build # Production build
|
|
306
|
-
pnpm lint # Lint code
|
|
307
|
-
pnpm typecheck # Type check
|
|
308
|
-
```
|
|
93
|
+
For complete API documentation, examples, and advanced usage, see the [full documentation](#).
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const U="0.1.0-beta.
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const U="0.1.0-beta.6",P={version:U},o="embedded::",p={INIT:`${o}iframe.ready`,RESIZE:`${o}iframe.resize`,READY:`${o}ready`,DESTROY:`${o}destroy`},I={PROVIDE:`${o}context.provide`,THEME_CHANGE:`${o}theme.change`},q={LOG:`${o}log`},z={REFRESH:`${o}auth.refresh`},m={NAVIGATE:`${o}page.navigate`,REDIRECT:`${o}page.redirect`,SET_TITLE:`${o}page.setTitle`},w={SET_ACTION:`${o}nav.setAction`,ACTION_CLICK:`${o}nav.actionClick`},c={LOADING:`${o}ui.loading`,TOAST:`${o}ui.toast`,MODAL:`${o}ui.modal`,CONFIRM:`${o}ui.confirm`,CONFIRM_RESPONSE:`${o}ui.confirm.response`,MODAL_RESPONSE:`${o}ui.modal.response`},L={CREATE:`${o}checkout.create`},C=P.version,K=1e4,V=["localhost","merchants.workers.dev","s.salla.sa",".salla.group",".salla.sa"];function F(t){try{const n=new URL(t).hostname;return V.some(i=>i.startsWith(".")?n.endsWith(i)||n===i.slice(1):n===i||n.startsWith(`${i}:`))}catch{return!1}}function j(){return typeof window>"u"||window.parent===window?null:window.parent}function l(t,e,n="*"){const i=j();if(!i){console.warn("[EmbeddedSDK] Not running in an iframe, cannot post to host");return}const r={event:t,...e};i.postMessage(r,n)}const f=new Map;let S=!1;function _(t){if(process.env.NODE_ENV==="production"&&!F(t.origin))return;const e=t.data;if(!e||typeof e.event!="string")return;const n=f.get(e.event);n&&n.forEach(r=>{try{r(e)}catch(s){console.error("[EmbeddedSDK] Error in message handler:",s)}});const i=f.get("*");i&&i.forEach(r=>{try{r(e)}catch(s){console.error("[EmbeddedSDK] Error in wildcard handler:",s)}})}function G(){S||typeof window>"u"||(window.addEventListener("message",_),S=!0)}function y(t,e){G(),f.has(t)||f.set(t,new Set);const n=f.get(t);return n.add(e),()=>{n.delete(e),n.size===0&&f.delete(t)}}function H(t,e=K){return new Promise((n,i)=>{const r=setTimeout(()=>{s(),i(new Error(`[EmbeddedSDK] Timeout waiting for "${t}" message`))},e),s=y(t,a=>{clearTimeout(r),s(),n(a)})})}function X(){f.clear(),S&&typeof window<"u"&&(window.removeEventListener("message",_),S=!1)}function W(){return typeof window>"u"?!1:window.parent!==window}const h=new Map,Y=3e4;function Z(){const t=Date.now(),e=Math.random().toString(36).slice(2,9);return`req_${t}_${e}`}function B(t,e={},n=Y){const i=Z();return new Promise((r,s)=>{const a=setTimeout(()=>{h.get(i)&&(h.delete(i),s(new Error(`[EmbeddedSDK] Request "${t}" timed out after ${n}ms`)))},n);h.set(i,{resolve:r,reject:s,timeout:a,event:t}),l(t,{...e,requestId:i})})}function N(t,e,n){const i=h.get(t);if(!i){console.warn(`[EmbeddedSDK] Received response for unknown request: ${t}`);return}clearTimeout(i.timeout),h.delete(t),n?i.reject(new Error(n)):i.resolve(e)}function J(t="SDK cleanup"){h.forEach((e,n)=>{clearTimeout(e.timeout),e.reject(new Error(`[EmbeddedSDK] Request ${n} cancelled: ${t}`))}),h.clear()}const Q="https://api.salla.dev";class b extends Error{constructor(e,n,i){super(e),this.status=n,this.response=i,this.name="ApiError"}}async function ee(t,e={}){const{method:n="GET",headers:i={},body:r,timeout:s=3e4}=e,a=`${Q}${t}`,E=new AbortController,T=setTimeout(()=>{E.abort()},s);try{const u=await fetch(a,{method:n,headers:{"Content-Type":"application/json",...i},body:r?JSON.stringify(r):void 0,signal:E.signal});clearTimeout(T);let v;const A=u.headers.get("content-type");if(A!=null&&A.includes("application/json")?v=await u.json():v=await u.text(),!u.ok)throw new b(`API request failed: ${u.statusText}`,u.status,v);return v}catch(u){throw clearTimeout(T),u instanceof b?u:u instanceof Error?u.name==="AbortError"?new b(`Request timeout after ${s}ms`):new b(`Request failed: ${u.message}`):new b("Unknown error occurred")}}function te(t){return{getToken(){return new URLSearchParams(window.location.search).get("token")},getAppId(){return new URLSearchParams(window.location.search).get("app_id")},refresh(){l(z.REFRESH,{})},async introspect(e={}){const n=e.token??this.getToken();if(!n)throw new Error("Token is required. Provide it as a parameter or in URL as ?token=XXX");const i=e.appId??this.getAppId();if(!i)throw new Error("App ID is required. Provide it as a parameter or in URL as ?app_id=XXX");return await ee("/exchange-authority/v1/introspect",{method:"POST",headers:{"S-Source":i,"Content-Type":"application/json"},body:{env:"prod",token:n,iss:"merchant-dashboard",subject:"embedded-page"}})}}}const $=["success","error","warning","info"];function ie(t){const e=[];return t.type===void 0||t.type===null?e.push("Toast type is required"):(typeof t.type!="string"||!$.includes(t.type))&&e.push(`Invalid toast type "${t.type}". Expected: ${$.join(" | ")}`),t.message===void 0||t.message===null?e.push("Toast message is required"):typeof t.message!="string"?e.push("Toast message must be a string"):t.message.trim()===""&&e.push("Toast message cannot be empty"),t.duration!==void 0&&t.duration!==null&&(typeof t.duration!="number"?e.push("Toast duration must be a number"):t.duration<0&&e.push("Toast duration cannot be negative")),{valid:e.length===0,errors:e}}function ne(t){const e=[];return typeof t!="object"||t===null?(e.push("Checkout payload must be an object"),{valid:!1,errors:e}):(t.amount!==void 0&&t.amount!==null&&(typeof t.amount!="number"?e.push("Checkout amount must be a number"):t.amount<0&&e.push("Checkout amount cannot be negative")),t.currency!==void 0&&t.currency!==null&&(typeof t.currency!="string"?e.push("Checkout currency must be a string"):t.currency.trim()===""&&e.push("Checkout currency cannot be empty")),t.items!==void 0&&t.items!==null&&(Array.isArray(t.items)||e.push("Checkout items must be an array")),{valid:e.length===0,errors:e})}function re(t){const e=[];return t.path===void 0||t.path===null?e.push("Navigation path is required"):typeof t.path!="string"?e.push("Navigation path must be a string"):t.path.trim()===""&&e.push("Navigation path cannot be empty"),t.replace!==void 0&&typeof t.replace!="boolean"&&e.push("Navigation replace option must be a boolean"),{valid:e.length===0,errors:e}}function se(t){const e=[];if(t.url===void 0||t.url===null)e.push("Redirect URL is required");else if(typeof t.url!="string")e.push("Redirect URL must be a string");else if(t.url.trim()==="")e.push("Redirect URL cannot be empty");else try{new URL(t.url)}catch{e.push(`Invalid redirect URL: "${t.url}"`)}return{valid:e.length===0,errors:e}}function ae(t){const e=[];return t.title===void 0||t.title===null?e.push("Nav action title is required"):typeof t.title!="string"&&e.push("Nav action title must be a string"),t.onClick!==void 0&&t.onClick!==null&&typeof t.onClick!="function"&&e.push("Nav action onClick must be a function"),t.value!==void 0&&t.value!==null&&typeof t.value!="string"&&e.push("Nav action value must be a string"),t.subTitle!==void 0&&t.subTitle!==null&&typeof t.subTitle!="string"&&e.push("Nav action subTitle must be a string"),t.icon!==void 0&&t.icon!==null&&typeof t.icon!="string"&&e.push("Nav action icon must be a string"),t.disabled!==void 0&&t.disabled!==null&&typeof t.disabled!="boolean"&&e.push("Nav action disabled must be a boolean"),t.extendedActions!==void 0&&t.extendedActions!==null&&(Array.isArray(t.extendedActions)?t.extendedActions.forEach((n,i)=>{if(typeof n!="object"||n===null){e.push(`Extended action at index ${i} must be an object`);return}const r=n;(!r.title||typeof r.title!="string")&&e.push(`Extended action at index ${i} is missing required "title" property`),r.subTitle!==void 0&&typeof r.subTitle!="string"&&e.push(`Extended action at index ${i} subTitle must be a string`),r.url!==void 0&&typeof r.url!="string"&&e.push(`Extended action at index ${i} url must be a string`),r.value!==void 0&&typeof r.value!="string"&&e.push(`Extended action at index ${i} value must be a string`),r.icon!==void 0&&typeof r.icon!="string"&&e.push(`Extended action at index ${i} icon must be a string`),r.disabled!==void 0&&typeof r.disabled!="boolean"&&e.push(`Extended action at index ${i} disabled must be a boolean`)}):e.push("Nav action extendedActions must be an array")),{valid:e.length===0,errors:e}}const D=["danger","warning","info"];function oe(t){const e=[];return t.title===void 0||t.title===null?e.push("Confirm dialog title is required"):typeof t.title!="string"?e.push("Confirm dialog title must be a string"):t.title.trim()===""&&e.push("Confirm dialog title cannot be empty"),t.message===void 0||t.message===null?e.push("Confirm dialog message is required"):typeof t.message!="string"?e.push("Confirm dialog message must be a string"):t.message.trim()===""&&e.push("Confirm dialog message cannot be empty"),t.confirmText!==void 0&&t.confirmText!==null&&typeof t.confirmText!="string"&&e.push("Confirm dialog confirmText must be a string"),t.cancelText!==void 0&&t.cancelText!==null&&typeof t.cancelText!="string"&&e.push("Confirm dialog cancelText must be a string"),t.variant!==void 0&&t.variant!==null&&(typeof t.variant!="string"||!D.includes(t.variant))&&e.push(`Invalid confirm variant "${t.variant}". Expected: ${D.join(" | ")}`),{valid:e.length===0,errors:e}}function d(t,e){console.error(`[EmbeddedSDK] Validation failed for ${t}:
|
|
2
2
|
`+e.map(n=>` • ${n}`).join(`
|
|
3
|
-
`))}function le(){return{navigate(t,e){const n=re({path:t,...e});if(!n.valid){d(m.NAVIGATE,n.errors);return}l(m.NAVIGATE,{path:t,state:e==null?void 0:e.state,replace:e==null?void 0:e.replace})},redirect(t){const e=se({url:t});if(!e.valid){d(m.REDIRECT,e.errors);return}l(m.REDIRECT,{url:t})},navTo(t,e){if(t.startsWith("http://")||t.startsWith("https://")){this.redirect(t);return}this.navigate(t,e)},resize(t){if(typeof t!="number"||t<0){d(p.RESIZE,["Height must be a non-negative number"]);return}l(p.RESIZE,{height:t})},autoResize(){const t=document.documentElement.scrollHeight;this.resize(t)},setTitle(t){if(typeof t!="string"||!t.trim()){d(m.SET_TITLE,["Title must be a non-empty string"]);return}l(m.SET_TITLE,{title:t})}}}function ue(){const t=new Set;let e=null;return y(w.ACTION_CLICK,i=>{if(e)try{e()}catch(r){console.error("[EmbeddedSDK] Error in onClick callback:",r)}t.forEach(r=>{try{r(i.url,i.value)}catch(s){console.error("[EmbeddedSDK] Error in action click callback:",s)}})}),{setAction(i){var s;const r=ae(i);if(!r.valid){d(w.SET_ACTION,r.errors);return}i.onClick?e=i.onClick:e=null,l(w.SET_ACTION,{title:i.title,onClick:i.onClick?!0:void 0,value:i.value,subTitle:i.subTitle,icon:i.icon,disabled:i.disabled,extendedActions:(s=i.extendedActions)==null?void 0:s.map(a=>({title:a.title,subTitle:a.subTitle,url:a.url,value:a.value,icon:a.icon,disabled:a.disabled}))})},clearAction(){e=null,l(w.SET_ACTION,{title:""})},onActionClick(i){return t.add(i),()=>{t.delete(i)}},primaryAction(i){this.setAction(i)},clearPrimaryAction(){this.clearAction()}}}function ce(){return{show(t="full"){l(c.LOADING,{status:!1,mode:t})},hide(){l(c.LOADING,{status:!0,mode:"full"})}}}function de(){const t=e=>{const n=ie(e);if(!n.valid){d(c.TOAST,n.errors);return}l(c.TOAST,{type:e.type,message:e.message,duration:e.duration})};return{show:t,success(e,n){t({type:"success",message:e,duration:n})},error(e,n){t({type:"error",message:e,duration:n})},warning(e,n){t({type:"warning",message:e,duration:n})},info(e,n){t({type:"info",message:e,duration:n})}}}function fe(){return{open(t,e){l(c.MODAL,{action:"open",id:t,content:e})},close(t){l(c.MODAL,{action:"close",id:t})}}}function he(){return async t=>{const e=oe(t);return e.valid?B(c.CONFIRM,{title:t.title,message:t.message,confirmText:t.confirmText??"Confirm",cancelText:t.cancelText??"Cancel",variant:t.variant??"info"}):(d(c.CONFIRM,e.errors),Promise.reject(new Error(e.errors.join(", "))))}}function me(){return{loading:ce(),toast:de(),modal:fe(),confirm:he()}}function ge(){return{create(t){const e=ne(t);if(!e.valid){d(L.CREATE,e.errors);return}l(L.CREATE,{payload:t})}}}const k={debug:!1,initialized:!1},Ee={theme:"light",width:0,locale:"ar",currency:"SAR"},O={ready:!1,initializing:!1,layout:{...Ee}};class M{constructor(){this.config={...k},this.state={...O},this.themeCallbacks=new Set,this.initCallbacks=new Set,this.appReady=!1,this.auth=te(),this.page=le(),this.nav=ue(),this.ui=me(),this.checkout=ge(),this.setupThemeListener(),this.setupResponseListeners()}getState(){return{ready:this.state.ready,initializing:this.state.initializing,layout:{...this.state.layout}}}getConfig(){return{...this.config}}isReady(){return this.state.ready}debugLog(...e){this.config.debug&&console.log(`[EmbeddedSDK v${
|
|
3
|
+
`))}function le(){return{navigate(t,e){const n=re({path:t,...e});if(!n.valid){d(m.NAVIGATE,n.errors);return}l(m.NAVIGATE,{path:t,state:e==null?void 0:e.state,replace:e==null?void 0:e.replace})},redirect(t){const e=se({url:t});if(!e.valid){d(m.REDIRECT,e.errors);return}l(m.REDIRECT,{url:t})},navTo(t,e){if(t.startsWith("http://")||t.startsWith("https://")){this.redirect(t);return}this.navigate(t,e)},resize(t){if(typeof t!="number"||t<0){d(p.RESIZE,["Height must be a non-negative number"]);return}l(p.RESIZE,{height:t})},autoResize(){const t=document.documentElement.scrollHeight;this.resize(t)},setTitle(t){if(typeof t!="string"||!t.trim()){d(m.SET_TITLE,["Title must be a non-empty string"]);return}l(m.SET_TITLE,{title:t})}}}function ue(){const t=new Set;let e=null;return y(w.ACTION_CLICK,i=>{if(e)try{e()}catch(r){console.error("[EmbeddedSDK] Error in onClick callback:",r)}t.forEach(r=>{try{r(i.url,i.value)}catch(s){console.error("[EmbeddedSDK] Error in action click callback:",s)}})}),{setAction(i){var s;const r=ae(i);if(!r.valid){d(w.SET_ACTION,r.errors);return}i.onClick?e=i.onClick:e=null,l(w.SET_ACTION,{title:i.title,onClick:i.onClick?!0:void 0,value:i.value,subTitle:i.subTitle,icon:i.icon,disabled:i.disabled,extendedActions:(s=i.extendedActions)==null?void 0:s.map(a=>({title:a.title,subTitle:a.subTitle,url:a.url,value:a.value,icon:a.icon,disabled:a.disabled}))})},clearAction(){e=null,l(w.SET_ACTION,{title:""})},onActionClick(i){return t.add(i),()=>{t.delete(i)}},primaryAction(i){this.setAction(i)},clearPrimaryAction(){this.clearAction()}}}function ce(){return{show(t="full"){l(c.LOADING,{status:!1,mode:t})},hide(){l(c.LOADING,{status:!0,mode:"full"})}}}function de(){const t=e=>{const n=ie(e);if(!n.valid){d(c.TOAST,n.errors);return}l(c.TOAST,{type:e.type,message:e.message,duration:e.duration})};return{show:t,success(e,n){t({type:"success",message:e,duration:n})},error(e,n){t({type:"error",message:e,duration:n})},warning(e,n){t({type:"warning",message:e,duration:n})},info(e,n){t({type:"info",message:e,duration:n})}}}function fe(){return{open(t,e){l(c.MODAL,{action:"open",id:t,content:e})},close(t){l(c.MODAL,{action:"close",id:t})}}}function he(){return async t=>{const e=oe(t);return e.valid?B(c.CONFIRM,{title:t.title,message:t.message,confirmText:t.confirmText??"Confirm",cancelText:t.cancelText??"Cancel",variant:t.variant??"info"}):(d(c.CONFIRM,e.errors),Promise.reject(new Error(e.errors.join(", "))))}}function me(){return{loading:ce(),toast:de(),modal:fe(),confirm:he()}}function ge(){return{create(t){const e=ne(t);if(!e.valid){d(L.CREATE,e.errors);return}l(L.CREATE,{payload:t})}}}const k={debug:!1,initialized:!1},Ee={theme:"light",width:0,locale:"ar",currency:"SAR"},O={ready:!1,initializing:!1,layout:{...Ee}};class M{constructor(){this.config={...k},this.state={...O},this.themeCallbacks=new Set,this.initCallbacks=new Set,this.appReady=!1,this.auth=te(),this.page=le(),this.nav=ue(),this.ui=me(),this.checkout=ge(),this.setupThemeListener(),this.setupResponseListeners()}getState(){return{ready:this.state.ready,initializing:this.state.initializing,layout:{...this.state.layout}}}getConfig(){return{...this.config}}isReady(){return this.state.ready}debugLog(...e){this.config.debug&&console.log(`[EmbeddedSDK v${C}]`,...e)}warn(...e){console.warn(`[EmbeddedSDK v${C}]`,...e)}setupThemeListener(){y(I.THEME_CHANGE,e=>{this.state.layout.theme=e.theme,this.debugLog("Theme changed:",e.theme),this.themeCallbacks.forEach(n=>{try{n(e.theme)}catch(i){console.error("[EmbeddedSDK] Error in theme callback:",i)}})})}setupResponseListeners(){y(c.CONFIRM_RESPONSE,e=>{this.debugLog("Received confirm response:",e),N(e.requestId,{confirmed:e.confirmed})}),y(c.MODAL_RESPONSE,e=>{this.debugLog("Received modal response:",e),N(e.requestId,e.result,e.error)})}onThemeChange(e){return this.themeCallbacks.add(e),()=>{this.themeCallbacks.delete(e)}}onInit(e){if(this.config.initialized)try{e(this.getState())}catch(n){console.error("[EmbeddedSDK] Error in init callback:",n)}return this.initCallbacks.add(e),()=>{this.initCallbacks.delete(e)}}log(e,n,i){l(q.LOG,{level:e,message:n,context:i})}ready(){if(this.appReady){this.debugLog("App already signaled as ready");return}if(!this.config.initialized){this.warn("Cannot signal ready before init() is called");return}this.appReady=!0,l(p.READY,{}),this.debugLog("Sent ready signal to host")}async init(e={}){var n,i,r,s;if(this.config.initialized)return this.debugLog("Already initialized, returning current layout"),{layout:{...this.state.layout}};if(this.state.initializing)return this.warn("Initialization already in progress"),this.waitForInit();W()||this.warn("Not running in an iframe. Some features may not work."),this.config={debug:e.debug??!1,initialized:!1},this.state.initializing=!0,this.debugLog("Initializing SDK...");try{l(p.INIT,{height:document.documentElement.scrollHeight}),this.debugLog("Sent iframe.ready message, waiting for context...");const a=await H(I.PROVIDE);this.debugLog("Received context from host:",a),this.state={ready:!0,initializing:!1,layout:{theme:((n=a.layout)==null?void 0:n.theme)??"light",width:((i=a.layout)==null?void 0:i.width)??0,locale:((r=a.layout)==null?void 0:r.locale)??"ar",currency:((s=a.layout)==null?void 0:s.currency)??"SAR"}},this.config.initialized=!0,this.debugLog("Initialization complete. Layout:",this.state.layout);const E=this.getState();return this.initCallbacks.forEach(T=>{try{T(E)}catch(u){console.error("[EmbeddedSDK] Error in init callback:",u)}}),{layout:{...this.state.layout}}}catch(a){throw this.state.initializing=!1,this.state.ready=!1,a}}waitForInit(){return new Promise(e=>{const n=this.onInit(i=>{n(),e({layout:{...i.layout}})})})}destroy(){this.debugLog("Destroying SDK instance"),this.config.initialized&&(l(p.DESTROY,{}),this.debugLog("Sent destroy event to host")),J("SDK destroyed"),X(),this.themeCallbacks.clear(),this.initCallbacks.clear(),this.config={...k},this.state={...O},this.appReady=!1}}let g=null;function x(){return g||(g=new M),g}function be(){g&&(g.destroy(),g=null)}const R=x(),pe=C;typeof window<"u"&&(window.salla=window.salla||window.Salla||{},window.Salla=window.salla,window.salla.embedded||(window.salla.embedded=R),window.Salla.embedded||(window.Salla.embedded=R));exports.EmbeddedApp=M;exports.embedded=R;exports.getEmbeddedApp=x;exports.resetEmbeddedApp=be;exports.version=pe;
|
|
4
4
|
//# sourceMappingURL=index.js.map
|