@salla.sa/embedded-sdk 0.1.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/LICENSE +201 -0
- package/README.md +280 -0
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/index.js +777 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/system/index.js +4 -0
- package/dist/system/index.js.map +1 -0
- package/dist/types/index.d.ts +308 -0
- package/dist/umd/index.js +4 -0
- package/dist/umd/index.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,777 @@
|
|
|
1
|
+
const O = "0.1.0-beta.1", $ = {
|
|
2
|
+
version: O
|
|
3
|
+
}, s = "embedded::", T = {
|
|
4
|
+
/** Initialize handshake - iframe signals it's ready */
|
|
5
|
+
READY: `${s}iframe.ready`,
|
|
6
|
+
/** Request iframe resize */
|
|
7
|
+
RESIZE: `${s}iframe.resize`
|
|
8
|
+
}, y = {
|
|
9
|
+
/** Context data provision */
|
|
10
|
+
PROVIDE: `${s}context.provide`,
|
|
11
|
+
/** Theme change notification */
|
|
12
|
+
THEME_CHANGE: `${s}theme.change`
|
|
13
|
+
}, L = {
|
|
14
|
+
/** Report error to host */
|
|
15
|
+
REPORT: `${s}error.report`
|
|
16
|
+
}, b = {
|
|
17
|
+
/** Request logout and redirect to auth */
|
|
18
|
+
LOGOUT: `${s}auth.logout`,
|
|
19
|
+
/** Request token refresh (triggers page reload) */
|
|
20
|
+
REFRESH: `${s}auth.refresh`,
|
|
21
|
+
/** Request token verification via API */
|
|
22
|
+
VERIFY: `${s}auth.verify`
|
|
23
|
+
}, h = {
|
|
24
|
+
/** Navigate using React Router (SPA navigation) */
|
|
25
|
+
NAVIGATE: `${s}page.navigate`,
|
|
26
|
+
/** Redirect using window.location (full page reload) */
|
|
27
|
+
REDIRECT: `${s}page.redirect`
|
|
28
|
+
}, g = {
|
|
29
|
+
/** Set primary action button in navbar */
|
|
30
|
+
SET_ACTION: `${s}nav.setAction`,
|
|
31
|
+
/** Notification when action button is clicked (host → iframe) */
|
|
32
|
+
ACTION_CLICK: `${s}nav.actionClick`
|
|
33
|
+
}, o = {
|
|
34
|
+
/** Set loading state */
|
|
35
|
+
LOADING: `${s}ui.loading`,
|
|
36
|
+
/** Set breadcrumb items */
|
|
37
|
+
BREADCRUMB: `${s}ui.breadcrumb`,
|
|
38
|
+
/** Control overlay state */
|
|
39
|
+
OVERLAY: `${s}ui.overlay`,
|
|
40
|
+
/** Show toast notification */
|
|
41
|
+
TOAST: `${s}ui.toast`,
|
|
42
|
+
/** Control modal state */
|
|
43
|
+
MODAL: `${s}ui.modal`,
|
|
44
|
+
/** Show confirm dialog (async request) */
|
|
45
|
+
CONFIRM: `${s}ui.confirm`,
|
|
46
|
+
/** Confirm dialog response (from host) */
|
|
47
|
+
CONFIRM_RESPONSE: `${s}ui.confirm.response`,
|
|
48
|
+
/** Modal response (from host) */
|
|
49
|
+
MODAL_RESPONSE: `${s}ui.modal.response`
|
|
50
|
+
}, w = {
|
|
51
|
+
/** Initialize checkout flow */
|
|
52
|
+
CREATE: `${s}checkout.create`
|
|
53
|
+
}, p = $.version, M = 1e4, k = [
|
|
54
|
+
"localhost",
|
|
55
|
+
"merchants.workers.dev",
|
|
56
|
+
"s.salla.sa",
|
|
57
|
+
".salla.group",
|
|
58
|
+
".salla.sa"
|
|
59
|
+
];
|
|
60
|
+
function _(t) {
|
|
61
|
+
try {
|
|
62
|
+
const r = new URL(t).hostname;
|
|
63
|
+
return k.some((n) => n.startsWith(".") ? r.endsWith(n) || r === n.slice(1) : r === n || r.startsWith(`${n}:`));
|
|
64
|
+
} catch {
|
|
65
|
+
return !1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function x() {
|
|
69
|
+
return typeof window > "u" || window.parent === window ? null : window.parent;
|
|
70
|
+
}
|
|
71
|
+
function i(t, e, r = "*") {
|
|
72
|
+
const n = x();
|
|
73
|
+
if (!n) {
|
|
74
|
+
console.warn("[EmbeddedSDK] Not running in an iframe, cannot post to host");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const a = {
|
|
78
|
+
event: t,
|
|
79
|
+
...e
|
|
80
|
+
};
|
|
81
|
+
n.postMessage(a, r);
|
|
82
|
+
}
|
|
83
|
+
const c = /* @__PURE__ */ new Map();
|
|
84
|
+
let E = !1;
|
|
85
|
+
function D(t) {
|
|
86
|
+
if (process.env.NODE_ENV === "production" && !_(t.origin))
|
|
87
|
+
return;
|
|
88
|
+
const e = t.data;
|
|
89
|
+
if (!e || typeof e.event != "string")
|
|
90
|
+
return;
|
|
91
|
+
const r = c.get(e.event);
|
|
92
|
+
r && r.forEach((a) => {
|
|
93
|
+
try {
|
|
94
|
+
a(e);
|
|
95
|
+
} catch (u) {
|
|
96
|
+
console.error("[EmbeddedSDK] Error in message handler:", u);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const n = c.get("*");
|
|
100
|
+
n && n.forEach((a) => {
|
|
101
|
+
try {
|
|
102
|
+
a(e);
|
|
103
|
+
} catch (u) {
|
|
104
|
+
console.error("[EmbeddedSDK] Error in wildcard handler:", u);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function U() {
|
|
109
|
+
E || typeof window > "u" || (window.addEventListener("message", D), E = !0);
|
|
110
|
+
}
|
|
111
|
+
function m(t, e) {
|
|
112
|
+
U(), c.has(t) || c.set(t, /* @__PURE__ */ new Set());
|
|
113
|
+
const r = c.get(t);
|
|
114
|
+
return r.add(e), () => {
|
|
115
|
+
r.delete(e), r.size === 0 && c.delete(t);
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function V(t, e = M) {
|
|
119
|
+
return new Promise((r, n) => {
|
|
120
|
+
const a = setTimeout(() => {
|
|
121
|
+
u(), n(new Error(`[EmbeddedSDK] Timeout waiting for "${t}" message`));
|
|
122
|
+
}, e), u = m(t, (v) => {
|
|
123
|
+
clearTimeout(a), u(), r(v);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function P() {
|
|
128
|
+
c.clear(), E && typeof window < "u" && (window.removeEventListener("message", D), E = !1);
|
|
129
|
+
}
|
|
130
|
+
function F() {
|
|
131
|
+
return typeof window > "u" ? !1 : window.parent !== window;
|
|
132
|
+
}
|
|
133
|
+
const d = /* @__PURE__ */ new Map(), K = 3e4;
|
|
134
|
+
function q() {
|
|
135
|
+
const t = Date.now(), e = Math.random().toString(36).slice(2, 9);
|
|
136
|
+
return `req_${t}_${e}`;
|
|
137
|
+
}
|
|
138
|
+
function z(t, e = {}, r = K) {
|
|
139
|
+
const n = q();
|
|
140
|
+
return new Promise((a, u) => {
|
|
141
|
+
const v = setTimeout(() => {
|
|
142
|
+
d.get(n) && (d.delete(n), u(
|
|
143
|
+
new Error(
|
|
144
|
+
`[EmbeddedSDK] Request "${t}" timed out after ${r}ms`
|
|
145
|
+
)
|
|
146
|
+
));
|
|
147
|
+
}, r);
|
|
148
|
+
d.set(n, {
|
|
149
|
+
resolve: a,
|
|
150
|
+
reject: u,
|
|
151
|
+
timeout: v,
|
|
152
|
+
event: t
|
|
153
|
+
}), i(t, { ...e, requestId: n });
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function A(t, e, r) {
|
|
157
|
+
const n = d.get(t);
|
|
158
|
+
if (!n) {
|
|
159
|
+
console.warn(
|
|
160
|
+
`[EmbeddedSDK] Received response for unknown request: ${t}`
|
|
161
|
+
);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
clearTimeout(n.timeout), d.delete(t), r ? n.reject(new Error(r)) : n.resolve(e);
|
|
165
|
+
}
|
|
166
|
+
function B(t = "SDK cleanup") {
|
|
167
|
+
d.forEach((e, r) => {
|
|
168
|
+
clearTimeout(e.timeout), e.reject(
|
|
169
|
+
new Error(`[EmbeddedSDK] Request ${r} cancelled: ${t}`)
|
|
170
|
+
);
|
|
171
|
+
}), d.clear();
|
|
172
|
+
}
|
|
173
|
+
function G(t) {
|
|
174
|
+
return {
|
|
175
|
+
/**
|
|
176
|
+
* Get the current access token.
|
|
177
|
+
*/
|
|
178
|
+
getAccessToken() {
|
|
179
|
+
return t().token;
|
|
180
|
+
},
|
|
181
|
+
/**
|
|
182
|
+
* Check if authenticated (has a valid token).
|
|
183
|
+
*/
|
|
184
|
+
isAuthenticated() {
|
|
185
|
+
const e = t();
|
|
186
|
+
return e.ready && !!e.token;
|
|
187
|
+
},
|
|
188
|
+
/**
|
|
189
|
+
* Get the current store ID.
|
|
190
|
+
*/
|
|
191
|
+
getStoreId() {
|
|
192
|
+
return t().storeId;
|
|
193
|
+
},
|
|
194
|
+
/**
|
|
195
|
+
* Get the current user ID.
|
|
196
|
+
*/
|
|
197
|
+
getUserId() {
|
|
198
|
+
return t().userId;
|
|
199
|
+
},
|
|
200
|
+
/**
|
|
201
|
+
* Get the merchant plan.
|
|
202
|
+
*/
|
|
203
|
+
getMerchantPlan() {
|
|
204
|
+
return t().merchantPlan;
|
|
205
|
+
},
|
|
206
|
+
/**
|
|
207
|
+
* Get the current locale.
|
|
208
|
+
*/
|
|
209
|
+
getLocale() {
|
|
210
|
+
return t().locale;
|
|
211
|
+
},
|
|
212
|
+
/**
|
|
213
|
+
* Request logout from the host.
|
|
214
|
+
* This will redirect to the auth page.
|
|
215
|
+
*/
|
|
216
|
+
logout(e) {
|
|
217
|
+
i(b.LOGOUT, { redirectUrl: e });
|
|
218
|
+
},
|
|
219
|
+
/**
|
|
220
|
+
* Request a token refresh from the host.
|
|
221
|
+
* This will trigger a page reload.
|
|
222
|
+
*/
|
|
223
|
+
refreshToken() {
|
|
224
|
+
i(b.REFRESH);
|
|
225
|
+
},
|
|
226
|
+
/**
|
|
227
|
+
* Request token verification from the host.
|
|
228
|
+
*/
|
|
229
|
+
verifyToken(e) {
|
|
230
|
+
i(b.VERIFY, { token: e });
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
const R = ["success", "error", "warning", "info"];
|
|
235
|
+
function j(t) {
|
|
236
|
+
const e = [];
|
|
237
|
+
return t.type === void 0 || t.type === null ? e.push("Toast type is required") : (typeof t.type != "string" || !R.includes(t.type)) && e.push(
|
|
238
|
+
`Invalid toast type "${t.type}". Expected: ${R.join(" | ")}`
|
|
239
|
+
), 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 };
|
|
240
|
+
}
|
|
241
|
+
function H(t) {
|
|
242
|
+
const e = [];
|
|
243
|
+
return Array.isArray(t) ? (t.forEach((r, n) => {
|
|
244
|
+
if (typeof r != "object" || r === null) {
|
|
245
|
+
e.push(`Breadcrumb item at index ${n} must be an object`);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const a = r;
|
|
249
|
+
a.label ? typeof a.label != "string" && e.push(`Breadcrumb item at index ${n} "label" must be a string`) : e.push(
|
|
250
|
+
`Breadcrumb item at index ${n} is missing required "label" property`
|
|
251
|
+
), a.path !== void 0 && typeof a.path != "string" && e.push(`Breadcrumb item at index ${n} "path" must be a string`);
|
|
252
|
+
}), { valid: e.length === 0, errors: e }) : (e.push("Breadcrumbs must be an array"), { valid: !1, errors: e });
|
|
253
|
+
}
|
|
254
|
+
function W(t) {
|
|
255
|
+
const e = [];
|
|
256
|
+
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 });
|
|
257
|
+
}
|
|
258
|
+
function Y(t) {
|
|
259
|
+
const e = [];
|
|
260
|
+
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 };
|
|
261
|
+
}
|
|
262
|
+
function Z(t) {
|
|
263
|
+
const e = [];
|
|
264
|
+
if (t.url === void 0 || t.url === null)
|
|
265
|
+
e.push("Redirect URL is required");
|
|
266
|
+
else if (typeof t.url != "string")
|
|
267
|
+
e.push("Redirect URL must be a string");
|
|
268
|
+
else if (t.url.trim() === "")
|
|
269
|
+
e.push("Redirect URL cannot be empty");
|
|
270
|
+
else
|
|
271
|
+
try {
|
|
272
|
+
new URL(t.url);
|
|
273
|
+
} catch {
|
|
274
|
+
e.push(`Invalid redirect URL: "${t.url}"`);
|
|
275
|
+
}
|
|
276
|
+
return { valid: e.length === 0, errors: e };
|
|
277
|
+
}
|
|
278
|
+
function X(t) {
|
|
279
|
+
const e = [];
|
|
280
|
+
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.url !== void 0 && t.url !== null && typeof t.url != "string" && e.push("Nav action URL must be a string"), t.value !== void 0 && t.value !== null && typeof t.value != "string" && e.push("Nav action value must be a string"), t.extendedActions !== void 0 && t.extendedActions !== null && (Array.isArray(t.extendedActions) ? t.extendedActions.forEach((r, n) => {
|
|
281
|
+
if (typeof r != "object" || r === null) {
|
|
282
|
+
e.push(`Extended action at index ${n} must be an object`);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
const a = r;
|
|
286
|
+
(!a.title || typeof a.title != "string") && e.push(
|
|
287
|
+
`Extended action at index ${n} is missing required "title" property`
|
|
288
|
+
);
|
|
289
|
+
}) : e.push("Nav action extendedActions must be an array")), { valid: e.length === 0, errors: e };
|
|
290
|
+
}
|
|
291
|
+
const S = ["danger", "warning", "info"];
|
|
292
|
+
function Q(t) {
|
|
293
|
+
const e = [];
|
|
294
|
+
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" || !S.includes(t.variant)) && e.push(
|
|
295
|
+
`Invalid confirm variant "${t.variant}". Expected: ${S.join(" | ")}`
|
|
296
|
+
), { valid: e.length === 0, errors: e };
|
|
297
|
+
}
|
|
298
|
+
function l(t, e) {
|
|
299
|
+
console.error(
|
|
300
|
+
`[EmbeddedSDK] Validation failed for ${t}:
|
|
301
|
+
` + e.map((r) => ` • ${r}`).join(`
|
|
302
|
+
`)
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
function J() {
|
|
306
|
+
return {
|
|
307
|
+
/**
|
|
308
|
+
* Navigate to a path using React Router (SPA navigation).
|
|
309
|
+
*/
|
|
310
|
+
navigate(t, e) {
|
|
311
|
+
const r = Y({ path: t, ...e });
|
|
312
|
+
if (!r.valid) {
|
|
313
|
+
l(h.NAVIGATE, r.errors);
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
i(h.NAVIGATE, {
|
|
317
|
+
path: t,
|
|
318
|
+
state: e == null ? void 0 : e.state,
|
|
319
|
+
replace: e == null ? void 0 : e.replace
|
|
320
|
+
});
|
|
321
|
+
},
|
|
322
|
+
/**
|
|
323
|
+
* Redirect to a URL (full page reload).
|
|
324
|
+
*/
|
|
325
|
+
redirect(t) {
|
|
326
|
+
const e = Z({ url: t });
|
|
327
|
+
if (!e.valid) {
|
|
328
|
+
l(h.REDIRECT, e.errors);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
i(h.REDIRECT, { url: t });
|
|
332
|
+
},
|
|
333
|
+
/**
|
|
334
|
+
* Navigate to a path - auto-detects internal vs external.
|
|
335
|
+
*/
|
|
336
|
+
navTo(t, e) {
|
|
337
|
+
if (t.startsWith("http://") || t.startsWith("https://")) {
|
|
338
|
+
this.redirect(t);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
this.navigate(t, e);
|
|
342
|
+
},
|
|
343
|
+
/**
|
|
344
|
+
* Update the iframe height.
|
|
345
|
+
*/
|
|
346
|
+
resize(t) {
|
|
347
|
+
if (typeof t != "number" || t < 0) {
|
|
348
|
+
l(T.RESIZE, [
|
|
349
|
+
"Height must be a non-negative number"
|
|
350
|
+
]);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
i(T.RESIZE, { height: t });
|
|
354
|
+
},
|
|
355
|
+
/**
|
|
356
|
+
* Auto-resize iframe to content height.
|
|
357
|
+
*/
|
|
358
|
+
autoResize() {
|
|
359
|
+
const t = document.documentElement.scrollHeight;
|
|
360
|
+
this.resize(t);
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
function ee() {
|
|
365
|
+
const t = /* @__PURE__ */ new Set();
|
|
366
|
+
return m(g.ACTION_CLICK, (e) => {
|
|
367
|
+
t.forEach((r) => {
|
|
368
|
+
try {
|
|
369
|
+
r(e.url, e.value);
|
|
370
|
+
} catch (n) {
|
|
371
|
+
console.error("[EmbeddedSDK] Error in action click callback:", n);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
}), {
|
|
375
|
+
/**
|
|
376
|
+
* Set the primary action button.
|
|
377
|
+
*/
|
|
378
|
+
setAction(e) {
|
|
379
|
+
const r = X(e);
|
|
380
|
+
if (!r.valid) {
|
|
381
|
+
l(g.SET_ACTION, r.errors);
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
i(g.SET_ACTION, {
|
|
385
|
+
title: e.title,
|
|
386
|
+
url: e.url,
|
|
387
|
+
value: e.value,
|
|
388
|
+
extendedActions: e.extendedActions
|
|
389
|
+
});
|
|
390
|
+
},
|
|
391
|
+
/**
|
|
392
|
+
* Clear the primary action button.
|
|
393
|
+
*/
|
|
394
|
+
clearAction() {
|
|
395
|
+
i(g.SET_ACTION, {
|
|
396
|
+
title: ""
|
|
397
|
+
});
|
|
398
|
+
},
|
|
399
|
+
/**
|
|
400
|
+
* Subscribe to action button clicks.
|
|
401
|
+
*/
|
|
402
|
+
onActionClick(e) {
|
|
403
|
+
return t.add(e), () => {
|
|
404
|
+
t.delete(e);
|
|
405
|
+
};
|
|
406
|
+
},
|
|
407
|
+
// Legacy aliases
|
|
408
|
+
primaryAction(e) {
|
|
409
|
+
this.setAction(e);
|
|
410
|
+
},
|
|
411
|
+
clearPrimaryAction() {
|
|
412
|
+
this.clearAction();
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
function te() {
|
|
417
|
+
return {
|
|
418
|
+
/**
|
|
419
|
+
* Show loading indicator.
|
|
420
|
+
*/
|
|
421
|
+
show(t = "full") {
|
|
422
|
+
i(o.LOADING, { status: !1, mode: t });
|
|
423
|
+
},
|
|
424
|
+
/**
|
|
425
|
+
* Hide loading indicator.
|
|
426
|
+
*/
|
|
427
|
+
hide() {
|
|
428
|
+
i(o.LOADING, { status: !0, mode: "full" });
|
|
429
|
+
},
|
|
430
|
+
/**
|
|
431
|
+
* Set the loading state directly.
|
|
432
|
+
*/
|
|
433
|
+
set(t, e = "full") {
|
|
434
|
+
i(o.LOADING, { status: t, mode: e });
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
function re() {
|
|
439
|
+
return {
|
|
440
|
+
/**
|
|
441
|
+
* Open overlay mode.
|
|
442
|
+
*/
|
|
443
|
+
open() {
|
|
444
|
+
i(o.OVERLAY, { action: "open" });
|
|
445
|
+
},
|
|
446
|
+
/**
|
|
447
|
+
* Close overlay mode.
|
|
448
|
+
*/
|
|
449
|
+
close() {
|
|
450
|
+
i(o.OVERLAY, { action: "close" });
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
function ne() {
|
|
455
|
+
return {
|
|
456
|
+
/**
|
|
457
|
+
* Set breadcrumb items.
|
|
458
|
+
*/
|
|
459
|
+
set(t) {
|
|
460
|
+
const e = H(t);
|
|
461
|
+
if (!e.valid) {
|
|
462
|
+
l(o.BREADCRUMB, e.errors);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
i(o.BREADCRUMB, { items: t });
|
|
466
|
+
},
|
|
467
|
+
/**
|
|
468
|
+
* Clear breadcrumbs.
|
|
469
|
+
*/
|
|
470
|
+
clear() {
|
|
471
|
+
i(o.BREADCRUMB, { items: [] });
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
function ie() {
|
|
476
|
+
const t = (e) => {
|
|
477
|
+
const r = j(e);
|
|
478
|
+
if (!r.valid) {
|
|
479
|
+
l(o.TOAST, r.errors);
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
i(o.TOAST, {
|
|
483
|
+
type: e.type,
|
|
484
|
+
message: e.message,
|
|
485
|
+
duration: e.duration
|
|
486
|
+
});
|
|
487
|
+
};
|
|
488
|
+
return {
|
|
489
|
+
/**
|
|
490
|
+
* Show a toast notification.
|
|
491
|
+
*/
|
|
492
|
+
show: t,
|
|
493
|
+
/**
|
|
494
|
+
* Show success toast.
|
|
495
|
+
*/
|
|
496
|
+
success(e, r) {
|
|
497
|
+
t({ type: "success", message: e, duration: r });
|
|
498
|
+
},
|
|
499
|
+
/**
|
|
500
|
+
* Show error toast.
|
|
501
|
+
*/
|
|
502
|
+
error(e, r) {
|
|
503
|
+
t({ type: "error", message: e, duration: r });
|
|
504
|
+
},
|
|
505
|
+
/**
|
|
506
|
+
* Show warning toast.
|
|
507
|
+
*/
|
|
508
|
+
warning(e, r) {
|
|
509
|
+
t({ type: "warning", message: e, duration: r });
|
|
510
|
+
},
|
|
511
|
+
/**
|
|
512
|
+
* Show info toast.
|
|
513
|
+
*/
|
|
514
|
+
info(e, r) {
|
|
515
|
+
t({ type: "info", message: e, duration: r });
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
function se() {
|
|
520
|
+
return {
|
|
521
|
+
/**
|
|
522
|
+
* Open a modal.
|
|
523
|
+
*/
|
|
524
|
+
open(t, e) {
|
|
525
|
+
i(o.MODAL, {
|
|
526
|
+
action: "open",
|
|
527
|
+
id: t,
|
|
528
|
+
content: e
|
|
529
|
+
});
|
|
530
|
+
},
|
|
531
|
+
/**
|
|
532
|
+
* Close a modal.
|
|
533
|
+
*/
|
|
534
|
+
close(t) {
|
|
535
|
+
i(o.MODAL, {
|
|
536
|
+
action: "close",
|
|
537
|
+
id: t
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
function ae() {
|
|
543
|
+
return async (t) => {
|
|
544
|
+
const e = Q(t);
|
|
545
|
+
return e.valid ? z(o.CONFIRM, {
|
|
546
|
+
title: t.title,
|
|
547
|
+
message: t.message,
|
|
548
|
+
confirmText: t.confirmText ?? "Confirm",
|
|
549
|
+
cancelText: t.cancelText ?? "Cancel",
|
|
550
|
+
variant: t.variant ?? "info"
|
|
551
|
+
}) : (l(o.CONFIRM, e.errors), Promise.reject(new Error(e.errors.join(", "))));
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
function oe() {
|
|
555
|
+
return {
|
|
556
|
+
loading: te(),
|
|
557
|
+
overlay: re(),
|
|
558
|
+
breadcrumbs: ne(),
|
|
559
|
+
toast: ie(),
|
|
560
|
+
modal: se(),
|
|
561
|
+
confirm: ae()
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
function ue() {
|
|
565
|
+
return {
|
|
566
|
+
/**
|
|
567
|
+
* Create/initiate a checkout.
|
|
568
|
+
*/
|
|
569
|
+
create(t) {
|
|
570
|
+
const e = W(t);
|
|
571
|
+
if (!e.valid) {
|
|
572
|
+
l(w.CREATE, e.errors);
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
i(w.CREATE, { payload: t });
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
const I = {
|
|
580
|
+
appId: "",
|
|
581
|
+
env: "prod",
|
|
582
|
+
debug: !1,
|
|
583
|
+
initialized: !1
|
|
584
|
+
}, C = {
|
|
585
|
+
ready: !1,
|
|
586
|
+
initializing: !1
|
|
587
|
+
};
|
|
588
|
+
class le {
|
|
589
|
+
constructor() {
|
|
590
|
+
this.config = { ...I }, this.state = { ...C }, this.themeCallbacks = /* @__PURE__ */ new Set(), this.auth = G(() => this.getState()), this.page = J(), this.nav = ee(), this.ui = oe(), this.checkout = ue(), this.setupThemeListener(), this.setupResponseListeners();
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Get current SDK state.
|
|
594
|
+
*/
|
|
595
|
+
getState() {
|
|
596
|
+
return { ...this.state };
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Get current SDK configuration.
|
|
600
|
+
*/
|
|
601
|
+
getConfig() {
|
|
602
|
+
return { ...this.config };
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Check if SDK is ready.
|
|
606
|
+
*/
|
|
607
|
+
isReady() {
|
|
608
|
+
return this.state.ready;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Log debug messages if debug mode is enabled.
|
|
612
|
+
*/
|
|
613
|
+
log(...e) {
|
|
614
|
+
this.config.debug && console.log(`[EmbeddedSDK v${p}]`, ...e);
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Log warnings.
|
|
618
|
+
*/
|
|
619
|
+
warn(...e) {
|
|
620
|
+
console.warn(`[EmbeddedSDK v${p}]`, ...e);
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Set up listener for theme changes from host.
|
|
624
|
+
*/
|
|
625
|
+
setupThemeListener() {
|
|
626
|
+
m(y.THEME_CHANGE, (e) => {
|
|
627
|
+
this.state.isDarkMode = e.dark, this.log("Theme changed:", e.dark ? "dark" : "light"), this.themeCallbacks.forEach((r) => {
|
|
628
|
+
try {
|
|
629
|
+
r(e.dark);
|
|
630
|
+
} catch (n) {
|
|
631
|
+
console.error("[EmbeddedSDK] Error in theme callback:", n);
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Set up listeners for async response events from host.
|
|
638
|
+
*/
|
|
639
|
+
setupResponseListeners() {
|
|
640
|
+
m(o.CONFIRM_RESPONSE, (e) => {
|
|
641
|
+
this.log("Received confirm response:", e), A(e.requestId, { confirmed: e.confirmed });
|
|
642
|
+
}), m(o.MODAL_RESPONSE, (e) => {
|
|
643
|
+
this.log("Received modal response:", e), A(e.requestId, e.result, e.error);
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Subscribe to theme changes.
|
|
648
|
+
*
|
|
649
|
+
* @param callback - Function called when theme changes
|
|
650
|
+
* @returns Unsubscribe function
|
|
651
|
+
*
|
|
652
|
+
* @example
|
|
653
|
+
* ```typescript
|
|
654
|
+
* const unsubscribe = embedded.onThemeChange((isDark) => {
|
|
655
|
+
* document.body.classList.toggle('dark-mode', isDark);
|
|
656
|
+
* });
|
|
657
|
+
* ```
|
|
658
|
+
*/
|
|
659
|
+
onThemeChange(e) {
|
|
660
|
+
return this.themeCallbacks.add(e), () => {
|
|
661
|
+
this.themeCallbacks.delete(e);
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* Report an error to the host.
|
|
666
|
+
*
|
|
667
|
+
* @param error - Error object or message
|
|
668
|
+
* @param context - Additional context
|
|
669
|
+
*
|
|
670
|
+
* @example
|
|
671
|
+
* ```typescript
|
|
672
|
+
* try {
|
|
673
|
+
* await riskyOperation();
|
|
674
|
+
* } catch (err) {
|
|
675
|
+
* embedded.reportError(err, { operation: 'riskyOperation' });
|
|
676
|
+
* }
|
|
677
|
+
* ```
|
|
678
|
+
*/
|
|
679
|
+
reportError(e, r) {
|
|
680
|
+
const n = typeof e == "string" ? { message: e } : {
|
|
681
|
+
message: e.message,
|
|
682
|
+
stack: e.stack,
|
|
683
|
+
code: e.code
|
|
684
|
+
};
|
|
685
|
+
i(L.REPORT, {
|
|
686
|
+
error: n,
|
|
687
|
+
context: r
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Initialize the SDK and establish connection with the host.
|
|
692
|
+
*
|
|
693
|
+
* @param options - Initialization options
|
|
694
|
+
* @returns Promise that resolves when SDK is ready
|
|
695
|
+
*
|
|
696
|
+
* @example
|
|
697
|
+
* ```typescript
|
|
698
|
+
* await embedded.init({
|
|
699
|
+
* app_id: 'my-app-123',
|
|
700
|
+
* env: 'prod',
|
|
701
|
+
* debug: true
|
|
702
|
+
* });
|
|
703
|
+
* ```
|
|
704
|
+
*/
|
|
705
|
+
async init(e) {
|
|
706
|
+
if (this.config.initialized)
|
|
707
|
+
return this.log("Already initialized, returning current state"), this.getState();
|
|
708
|
+
if (this.state.initializing)
|
|
709
|
+
return this.warn("Initialization already in progress"), this.waitForReady();
|
|
710
|
+
if (!e.app_id)
|
|
711
|
+
throw new Error("[EmbeddedSDK] app_id is required");
|
|
712
|
+
F() || this.warn("Not running in an iframe. Some features may not work."), this.config = {
|
|
713
|
+
appId: e.app_id,
|
|
714
|
+
env: e.env ?? "prod",
|
|
715
|
+
debug: e.debug ?? !1,
|
|
716
|
+
initialized: !1
|
|
717
|
+
}, this.state.initializing = !0, this.log("Initializing with options:", e);
|
|
718
|
+
try {
|
|
719
|
+
i(T.READY, {
|
|
720
|
+
height: document.documentElement.scrollHeight
|
|
721
|
+
}), this.log("Sent iframe.ready message, waiting for context...");
|
|
722
|
+
const r = await V(
|
|
723
|
+
y.PROVIDE
|
|
724
|
+
);
|
|
725
|
+
return this.log("Received context from host:", r), this.state = {
|
|
726
|
+
ready: !0,
|
|
727
|
+
initializing: !1,
|
|
728
|
+
token: r.token,
|
|
729
|
+
storeId: r.storeId,
|
|
730
|
+
userId: r.userId,
|
|
731
|
+
merchantPlan: r.plan,
|
|
732
|
+
isDarkMode: r.isDarkMode,
|
|
733
|
+
parentWidth: r.parentWidth,
|
|
734
|
+
baseUrl: r.baseUrl,
|
|
735
|
+
baseApiUrl: r.baseApiUrl,
|
|
736
|
+
locale: r.locale
|
|
737
|
+
}, this.config.initialized = !0, this.log("Initialization complete. State:", this.state), this.getState();
|
|
738
|
+
} catch (r) {
|
|
739
|
+
throw this.state.initializing = !1, this.state.ready = !1, r;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Wait for the SDK to be ready.
|
|
744
|
+
* Useful when multiple calls to init() might happen.
|
|
745
|
+
*/
|
|
746
|
+
waitForReady() {
|
|
747
|
+
return new Promise((e) => {
|
|
748
|
+
const r = () => {
|
|
749
|
+
this.state.ready ? e(this.getState()) : setTimeout(r, 100);
|
|
750
|
+
};
|
|
751
|
+
r();
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Destroy the SDK instance and clean up resources.
|
|
756
|
+
*/
|
|
757
|
+
destroy() {
|
|
758
|
+
this.log("Destroying SDK instance"), B("SDK destroyed"), P(), this.themeCallbacks.clear(), this.config = { ...I }, this.state = { ...C };
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
let f = null;
|
|
762
|
+
function ce() {
|
|
763
|
+
return f || (f = new le()), f;
|
|
764
|
+
}
|
|
765
|
+
function fe() {
|
|
766
|
+
f && (f.destroy(), f = null);
|
|
767
|
+
}
|
|
768
|
+
const N = ce(), me = p;
|
|
769
|
+
typeof window < "u" && (window.salla = window.salla || window.Salla || {}, window.Salla = window.salla, window.salla.embedded || (window.salla.embedded = N), window.Salla.embedded || (window.Salla.embedded = N));
|
|
770
|
+
export {
|
|
771
|
+
le as EmbeddedApp,
|
|
772
|
+
N as embedded,
|
|
773
|
+
ce as getEmbeddedApp,
|
|
774
|
+
fe as resetEmbeddedApp,
|
|
775
|
+
me as version
|
|
776
|
+
};
|
|
777
|
+
//# sourceMappingURL=index.js.map
|