@salla.sa/embedded-sdk 0.1.0-beta.1 → 0.1.0-beta.11

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/esm/index.js CHANGED
@@ -1,42 +1,23 @@
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`,
1
+ const s = "embedded::", y = {
2
+ /** Initialize handshake - iframe signals it's ready to receive context */
3
+ INIT: `${s}iframe.ready`,
6
4
  /** Request iframe resize */
7
- RESIZE: `${s}iframe.resize`
8
- }, y = {
5
+ RESIZE: `${s}iframe.resize`,
6
+ /** App signals it's fully loaded and ready */
7
+ READY: `${s}ready`,
8
+ /** App requests to be destroyed and navigate away */
9
+ DESTROY: `${s}destroy`
10
+ }, k = {
9
11
  /** Context data provision */
10
12
  PROVIDE: `${s}context.provide`,
11
13
  /** Theme change notification */
12
14
  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 = {
15
+ }, j = {
16
+ /** Send log message to host */
17
+ LOG: `${s}log`
18
+ }, d = {
34
19
  /** Set loading state */
35
20
  LOADING: `${s}ui.loading`,
36
- /** Set breadcrumb items */
37
- BREADCRUMB: `${s}ui.breadcrumb`,
38
- /** Control overlay state */
39
- OVERLAY: `${s}ui.overlay`,
40
21
  /** Show toast notification */
41
22
  TOAST: `${s}ui.toast`,
42
23
  /** Control modal state */
@@ -47,553 +28,677 @@ const O = "0.1.0-beta.1", $ = {
47
28
  CONFIRM_RESPONSE: `${s}ui.confirm.response`,
48
29
  /** Modal response (from host) */
49
30
  MODAL_RESPONSE: `${s}ui.modal.response`
31
+ }, G = "0.1.0-beta.11", H = {
32
+ version: G
33
+ }, z = {
34
+ /** Request token refresh (re-renders iframe with new token) */
35
+ REFRESH: `${s}auth.refresh`
36
+ }, m = {
37
+ /** Navigate using React Router (SPA navigation) */
38
+ NAVIGATE: `${s}page.navigate`,
39
+ /** Redirect using window.location (full page reload) */
40
+ REDIRECT: `${s}page.redirect`,
41
+ /** Set page title */
42
+ SET_TITLE: `${s}page.setTitle`
50
43
  }, w = {
44
+ /** Set primary action button in navbar */
45
+ SET_ACTION: `${s}nav.setAction`,
46
+ /** Notification when action button is clicked (host → iframe) */
47
+ ACTION_CLICK: `${s}nav.actionClick`
48
+ }, $ = {
51
49
  /** Initialize checkout flow */
52
50
  CREATE: `${s}checkout.create`
53
- }, p = $.version, M = 1e4, k = [
51
+ }, L = H.version, K = 1e4, X = [
54
52
  "localhost",
55
53
  "merchants.workers.dev",
56
54
  "s.salla.sa",
57
55
  ".salla.group",
58
56
  ".salla.sa"
59
57
  ];
60
- function _(t) {
58
+ let A = {
59
+ showVersion: !0,
60
+ debug: !1
61
+ };
62
+ function W(e) {
63
+ A = { ...A, ...e };
64
+ }
65
+ function O(e) {
66
+ return `%c${e}`;
67
+ }
68
+ function _(e, t = "#fff") {
69
+ return `background-color: ${e}; color: ${t}; padding: 2px 6px; border-radius: 3px; font-weight: 500; font-size: 11px;`;
70
+ }
71
+ function b(e, ...t) {
72
+ if (e === "debug" && !A.debug)
73
+ return;
74
+ const i = [], r = [];
75
+ i.push(O("EmbeddedSDK")), r.push(_("#10b981", "#fff")), A.showVersion && (i.push(O(`v${L}`)), r.push(_("#6b7280", "#fff")));
76
+ const n = i.join("").trim();
77
+ (console[e] || console.log)(n, ...r, ...t);
78
+ }
79
+ const u = {
80
+ log: (...e) => {
81
+ b("log", ...e);
82
+ },
83
+ warn: (...e) => {
84
+ b("warn", ...e);
85
+ },
86
+ error: (...e) => {
87
+ b("error", ...e);
88
+ },
89
+ info: (...e) => {
90
+ b("info", ...e);
91
+ },
92
+ debug: (...e) => {
93
+ b("debug", ...e);
94
+ }
95
+ };
96
+ function Y(e) {
61
97
  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}:`));
98
+ const i = new URL(e).hostname;
99
+ return X.some((r) => r.startsWith(".") ? i.endsWith(r) || i === r.slice(1) : i === r || i.startsWith(`${r}:`));
64
100
  } catch {
65
101
  return !1;
66
102
  }
67
103
  }
68
- function x() {
104
+ function B() {
69
105
  return typeof window > "u" || window.parent === window ? null : window.parent;
70
106
  }
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");
107
+ function o(e, t, i = "*", r, n) {
108
+ const a = B();
109
+ if (!a) {
110
+ u.warn("Not running in an iframe, cannot post to host");
75
111
  return;
76
112
  }
77
- const a = {
78
- event: t,
79
- ...e
113
+ const l = {
114
+ event: e,
115
+ payload: t || {},
116
+ timestamp: Date.now(),
117
+ source: "embedded-app",
118
+ ...r && { requestId: r },
119
+ metadata: {
120
+ version: L
121
+ }
80
122
  };
81
- n.postMessage(a, r);
123
+ a.postMessage(l, i);
82
124
  }
83
- const c = /* @__PURE__ */ new Map();
84
- let E = !1;
85
- function D(t) {
86
- if (process.env.NODE_ENV === "production" && !_(t.origin))
125
+ const h = /* @__PURE__ */ new Map();
126
+ let S = !1;
127
+ function P(e) {
128
+ if (process.env.NODE_ENV === "production" && !Y(e.origin))
87
129
  return;
88
- const e = t.data;
89
- if (!e || typeof e.event != "string")
130
+ const t = e.data;
131
+ if (!t || typeof t.event != "string" || !t.payload || typeof t.timestamp != "number" || !t.source) {
132
+ u.warn("Invalid message structure received:", t);
90
133
  return;
91
- const r = c.get(e.event);
92
- r && r.forEach((a) => {
134
+ }
135
+ const i = h.get(t.event);
136
+ i && i.forEach((n) => {
93
137
  try {
94
- a(e);
95
- } catch (u) {
96
- console.error("[EmbeddedSDK] Error in message handler:", u);
138
+ n(t);
139
+ } catch (a) {
140
+ u.error("Error in message handler:", a);
97
141
  }
98
142
  });
99
- const n = c.get("*");
100
- n && n.forEach((a) => {
143
+ const r = h.get("*");
144
+ r && r.forEach((n) => {
101
145
  try {
102
- a(e);
103
- } catch (u) {
104
- console.error("[EmbeddedSDK] Error in wildcard handler:", u);
146
+ n(t);
147
+ } catch (a) {
148
+ u.error("Error in wildcard handler:", a);
105
149
  }
106
150
  });
107
151
  }
108
- function U() {
109
- E || typeof window > "u" || (window.addEventListener("message", D), E = !0);
152
+ function Z() {
153
+ S || typeof window > "u" || (window.addEventListener("message", P), S = !0);
110
154
  }
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);
155
+ function T(e, t) {
156
+ Z(), h.has(e) || h.set(e, /* @__PURE__ */ new Set());
157
+ const i = h.get(e);
158
+ return i.add(t), () => {
159
+ i.delete(t), i.size === 0 && h.delete(e);
116
160
  };
117
161
  }
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);
162
+ function J(e, t = K) {
163
+ return new Promise((i, r) => {
164
+ const n = setTimeout(() => {
165
+ a(), r(new Error(`[EmbeddedSDK] Timeout waiting for "${e}" message`));
166
+ }, t), a = T(e, (l) => {
167
+ clearTimeout(n), a(), i(l);
124
168
  });
125
169
  });
126
170
  }
127
- function P() {
128
- c.clear(), E && typeof window < "u" && (window.removeEventListener("message", D), E = !1);
171
+ function Q() {
172
+ h.clear(), S && typeof window < "u" && (window.removeEventListener("message", P), S = !1);
129
173
  }
130
- function F() {
174
+ function ee() {
131
175
  return typeof window > "u" ? !1 : window.parent !== window;
132
176
  }
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(
177
+ const g = /* @__PURE__ */ new Map(), te = 3e4;
178
+ function re() {
179
+ const e = Date.now(), t = Math.random().toString(36).slice(2, 9);
180
+ return `req_${e}_${t}`;
181
+ }
182
+ function ie(e, t = {}, i = te) {
183
+ const r = re();
184
+ return new Promise((n, a) => {
185
+ const l = setTimeout(() => {
186
+ g.get(r) && (g.delete(r), a(
143
187
  new Error(
144
- `[EmbeddedSDK] Request "${t}" timed out after ${r}ms`
188
+ `[EmbeddedSDK] Request "${e}" timed out after ${i}ms`
145
189
  )
146
190
  ));
147
- }, r);
148
- d.set(n, {
149
- resolve: a,
150
- reject: u,
151
- timeout: v,
152
- event: t
153
- }), i(t, { ...e, requestId: n });
191
+ }, i);
192
+ g.set(r, {
193
+ resolve: n,
194
+ reject: a,
195
+ timeout: l,
196
+ event: e
197
+ }), o(e, t, "*", r);
154
198
  });
155
199
  }
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
- );
200
+ function D(e, t, i) {
201
+ const r = g.get(e);
202
+ if (!r) {
203
+ u.warn(`Received response for unknown request: ${e}`);
162
204
  return;
163
205
  }
164
- clearTimeout(n.timeout), d.delete(t), r ? n.reject(new Error(r)) : n.resolve(e);
206
+ clearTimeout(r.timeout), g.delete(e), i ? r.reject(new Error(i)) : r.resolve(t);
165
207
  }
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}`)
208
+ function ne(e = "SDK cleanup") {
209
+ g.forEach((t, i) => {
210
+ clearTimeout(t.timeout), t.reject(
211
+ new Error(`[EmbeddedSDK] Request ${i} cancelled: ${e}`)
170
212
  );
171
- }), d.clear();
213
+ }), g.clear();
172
214
  }
173
- function G(t) {
215
+ const ae = "https://api.salla.dev";
216
+ class E extends Error {
217
+ constructor(t, i, r) {
218
+ super(t), this.status = i, this.response = r, this.name = "ApiError";
219
+ }
220
+ }
221
+ async function se(e, t = {}) {
222
+ const { method: i = "GET", headers: r = {}, body: n, timeout: a = 3e4 } = t, l = `${ae}${e}`, R = new AbortController(), N = setTimeout(() => {
223
+ R.abort();
224
+ }, a);
225
+ try {
226
+ const c = await fetch(l, {
227
+ method: i,
228
+ headers: {
229
+ "Content-Type": "application/json",
230
+ ...r
231
+ },
232
+ body: n ? JSON.stringify(n) : void 0,
233
+ signal: R.signal
234
+ });
235
+ clearTimeout(N);
236
+ let v;
237
+ const C = c.headers.get("content-type");
238
+ if (C != null && C.includes("application/json") ? v = await c.json() : v = await c.text(), !c.ok)
239
+ throw new E(
240
+ `API request failed: ${c.statusText}`,
241
+ c.status,
242
+ v
243
+ );
244
+ return v;
245
+ } catch (c) {
246
+ throw clearTimeout(N), c instanceof E ? c : c instanceof Error ? c.name === "AbortError" ? new E(`Request timeout after ${a}ms`) : new E(`Request failed: ${c.message}`) : new E("Unknown error occurred");
247
+ }
248
+ }
249
+ function I(e) {
250
+ return {
251
+ isVerified: !1,
252
+ isError: !0,
253
+ error: e,
254
+ data: null
255
+ };
256
+ }
257
+ async function oe(e) {
258
+ const { token: t, appId: i, refreshOnError: r = !0 } = e;
259
+ if (!t) {
260
+ const n = "Token is required. Provide it as a parameter or in URL as ?token=XXX";
261
+ return u.error("Error in introspect:", n), I(n);
262
+ }
263
+ if (!i) {
264
+ const n = "App ID is required. Provide it as a parameter or in URL as ?app_id=XXX";
265
+ return u.error("Error in introspect:", n), I(n);
266
+ }
267
+ try {
268
+ const n = await se(
269
+ "/exchange-authority/v1/introspect",
270
+ {
271
+ method: "POST",
272
+ headers: {
273
+ "S-Source": i,
274
+ "Content-Type": "application/json"
275
+ },
276
+ body: {
277
+ env: "prod",
278
+ token: t,
279
+ iss: "merchant-dashboard",
280
+ subject: "embedded-page"
281
+ }
282
+ }
283
+ ), a = n.success;
284
+ return {
285
+ isVerified: a,
286
+ isError: !a,
287
+ error: a ? void 0 : "API request failed",
288
+ data: a ? n.data : null
289
+ };
290
+ } catch (n) {
291
+ r && (F().ui.toast.error((n == null ? void 0 : n.toString()) ?? "Introspect error"), o(z.REFRESH, {})), u.error("Error in introspect:", n);
292
+ const a = n instanceof Error ? n.message : n;
293
+ return I(a);
294
+ }
295
+ }
296
+ function le(e) {
174
297
  return {
175
298
  /**
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;
299
+ * Get the token from the URL query parameter.
300
+ * The token is passed to the iframe via ?token=XXX
301
+ *
302
+ * @example
303
+ * ```typescript
304
+ * const token = embedded.auth.getToken();
305
+ * if (token) {
306
+ * await verifyWithBackend(token);
307
+ * }
308
+ * ```
309
+ */
310
+ getToken() {
311
+ return new URLSearchParams(window.location.search).get("token");
211
312
  },
212
313
  /**
213
- * Request logout from the host.
214
- * This will redirect to the auth page.
314
+ * Get the app ID from the URL query parameter.
315
+ * The app ID is passed to the iframe via ?app_id=XXX
215
316
  */
216
- logout(e) {
217
- i(b.LOGOUT, { redirectUrl: e });
317
+ getAppId() {
318
+ return new URLSearchParams(window.location.search).get("app_id");
218
319
  },
219
320
  /**
220
321
  * Request a token refresh from the host.
221
- * This will trigger a page reload.
222
- */
223
- refreshToken() {
224
- i(b.REFRESH);
322
+ * This will re-render the iframe with a new token URL.
323
+ *
324
+ * @example
325
+ * ```typescript
326
+ * // When token is about to expire
327
+ * embedded.auth.refresh();
328
+ * ```
329
+ */
330
+ refresh() {
331
+ o(z.REFRESH, {});
225
332
  },
226
333
  /**
227
- * Request token verification from the host.
228
- */
229
- verifyToken(e) {
230
- i(b.VERIFY, { token: e });
334
+ * Introspect (verify) a short-lived token with Salla's API.
335
+ * This method verifies the token and returns token information.
336
+ *
337
+ * @param options - Optional parameters (appId, token, and refreshOnError). If not provided, will be extracted from URL params.
338
+ * @returns Promise that resolves with the introspect response. On API error, resolves with isVerified: false, isError: true, and empty data.
339
+ */
340
+ async introspect(t = {}) {
341
+ const i = t.token ?? this.getToken() ?? "", r = t.appId ?? this.getAppId() ?? "";
342
+ return oe({
343
+ token: i,
344
+ appId: r,
345
+ refreshOnError: t.refreshOnError
346
+ });
231
347
  }
232
348
  };
233
349
  }
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");
350
+ const M = ["success", "error", "warning", "info"];
351
+ function ue(e) {
352
+ const t = [];
353
+ return e.type === void 0 || e.type === null ? t.push("Toast type is required") : (typeof e.type != "string" || !M.includes(e.type)) && t.push(
354
+ `Invalid toast type "${e.type}". Expected: ${M.join(" | ")}`
355
+ ), e.message === void 0 || e.message === null ? t.push("Toast message is required") : typeof e.message != "string" ? t.push("Toast message must be a string") : e.message.trim() === "" && t.push("Toast message cannot be empty"), e.duration !== void 0 && e.duration !== null && (typeof e.duration != "number" ? t.push("Toast duration must be a number") : e.duration < 0 && t.push("Toast duration cannot be negative")), { valid: t.length === 0, errors: t };
356
+ }
357
+ function ce(e) {
358
+ const t = [];
359
+ return typeof e != "object" || e === null ? (t.push("Checkout payload must be an object"), { valid: !1, errors: t }) : (e.amount !== void 0 && e.amount !== null && (typeof e.amount != "number" ? t.push("Checkout amount must be a number") : e.amount < 0 && t.push("Checkout amount cannot be negative")), e.currency !== void 0 && e.currency !== null && (typeof e.currency != "string" ? t.push("Checkout currency must be a string") : e.currency.trim() === "" && t.push("Checkout currency cannot be empty")), e.items !== void 0 && e.items !== null && (Array.isArray(e.items) || t.push("Checkout items must be an array")), { valid: t.length === 0, errors: t });
360
+ }
361
+ function de(e) {
362
+ const t = [];
363
+ return e.path === void 0 || e.path === null ? t.push("Navigation path is required") : typeof e.path != "string" ? t.push("Navigation path must be a string") : e.path.trim() === "" && t.push("Navigation path cannot be empty"), e.replace !== void 0 && typeof e.replace != "boolean" && t.push("Navigation replace option must be a boolean"), { valid: t.length === 0, errors: t };
364
+ }
365
+ function fe(e) {
366
+ const t = [];
367
+ if (e.url === void 0 || e.url === null)
368
+ t.push("Redirect URL is required");
369
+ else if (typeof e.url != "string")
370
+ t.push("Redirect URL must be a string");
371
+ else if (e.url.trim() === "")
372
+ t.push("Redirect URL cannot be empty");
270
373
  else
271
374
  try {
272
- new URL(t.url);
375
+ new URL(e.url);
273
376
  } catch {
274
- e.push(`Invalid redirect URL: "${t.url}"`);
377
+ t.push(`Invalid redirect URL: "${e.url}"`);
275
378
  }
276
- return { valid: e.length === 0, errors: e };
379
+ return { valid: t.length === 0, errors: t };
277
380
  }
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`);
381
+ function he(e) {
382
+ const t = [];
383
+ return e.title === void 0 || e.title === null ? t.push("Nav action title is required") : typeof e.title != "string" && t.push("Nav action title must be a string"), e.onClick !== void 0 && e.onClick !== null && typeof e.onClick != "function" && t.push("Nav action onClick must be a function"), e.value !== void 0 && e.value !== null && typeof e.value != "string" && t.push("Nav action value must be a string"), e.subTitle !== void 0 && e.subTitle !== null && typeof e.subTitle != "string" && t.push("Nav action subTitle must be a string"), e.icon !== void 0 && e.icon !== null && typeof e.icon != "string" && t.push("Nav action icon must be a string"), e.disabled !== void 0 && e.disabled !== null && typeof e.disabled != "boolean" && t.push("Nav action disabled must be a boolean"), e.extendedActions !== void 0 && e.extendedActions !== null && (Array.isArray(e.extendedActions) ? e.extendedActions.forEach((i, r) => {
384
+ if (typeof i != "object" || i === null) {
385
+ t.push(`Extended action at index ${r} must be an object`);
283
386
  return;
284
387
  }
285
- const a = r;
286
- (!a.title || typeof a.title != "string") && e.push(
287
- `Extended action at index ${n} is missing required "title" property`
388
+ const n = i;
389
+ (!n.title || typeof n.title != "string") && t.push(
390
+ `Extended action at index ${r} is missing required "title" property`
391
+ ), n.subTitle !== void 0 && typeof n.subTitle != "string" && t.push(
392
+ `Extended action at index ${r} subTitle must be a string`
393
+ ), n.url !== void 0 && typeof n.url != "string" && t.push(`Extended action at index ${r} url must be a string`), n.value !== void 0 && typeof n.value != "string" && t.push(
394
+ `Extended action at index ${r} value must be a string`
395
+ ), n.icon !== void 0 && typeof n.icon != "string" && t.push(
396
+ `Extended action at index ${r} icon must be a string`
397
+ ), n.disabled !== void 0 && typeof n.disabled != "boolean" && t.push(
398
+ `Extended action at index ${r} disabled must be a boolean`
288
399
  );
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(`
400
+ }) : t.push("Nav action extendedActions must be an array")), { valid: t.length === 0, errors: t };
401
+ }
402
+ const x = ["danger", "warning", "info"];
403
+ function ge(e) {
404
+ const t = [];
405
+ return e.title === void 0 || e.title === null ? t.push("Confirm dialog title is required") : typeof e.title != "string" ? t.push("Confirm dialog title must be a string") : e.title.trim() === "" && t.push("Confirm dialog title cannot be empty"), e.message === void 0 || e.message === null ? t.push("Confirm dialog message is required") : typeof e.message != "string" ? t.push("Confirm dialog message must be a string") : e.message.trim() === "" && t.push("Confirm dialog message cannot be empty"), e.confirmText !== void 0 && e.confirmText !== null && typeof e.confirmText != "string" && t.push("Confirm dialog confirmText must be a string"), e.cancelText !== void 0 && e.cancelText !== null && typeof e.cancelText != "string" && t.push("Confirm dialog cancelText must be a string"), e.variant !== void 0 && e.variant !== null && (typeof e.variant != "string" || !x.includes(e.variant)) && t.push(
406
+ `Invalid confirm variant "${e.variant}". Expected: ${x.join(" | ")}`
407
+ ), { valid: t.length === 0, errors: t };
408
+ }
409
+ function f(e, t) {
410
+ u.error(
411
+ `Validation failed for ${e}:
412
+ ` + t.map((i) => ` • ${i}`).join(`
302
413
  `)
303
414
  );
304
415
  }
305
- function J() {
416
+ function me() {
306
417
  return {
307
418
  /**
308
419
  * Navigate to a path using React Router (SPA navigation).
309
420
  */
310
- navigate(t, e) {
311
- const r = Y({ path: t, ...e });
312
- if (!r.valid) {
313
- l(h.NAVIGATE, r.errors);
421
+ navigate(e, t) {
422
+ const i = de({ path: e, ...t });
423
+ if (!i.valid) {
424
+ f(m.NAVIGATE, i.errors);
314
425
  return;
315
426
  }
316
- i(h.NAVIGATE, {
317
- path: t,
318
- state: e == null ? void 0 : e.state,
319
- replace: e == null ? void 0 : e.replace
427
+ o(m.NAVIGATE, {
428
+ path: e,
429
+ state: t == null ? void 0 : t.state,
430
+ replace: t == null ? void 0 : t.replace
320
431
  });
321
432
  },
322
433
  /**
323
434
  * Redirect to a URL (full page reload).
324
435
  */
325
- redirect(t) {
326
- const e = Z({ url: t });
327
- if (!e.valid) {
328
- l(h.REDIRECT, e.errors);
436
+ redirect(e) {
437
+ const t = fe({ url: e });
438
+ if (!t.valid) {
439
+ f(m.REDIRECT, t.errors);
329
440
  return;
330
441
  }
331
- i(h.REDIRECT, { url: t });
442
+ o(m.REDIRECT, { url: e });
332
443
  },
333
444
  /**
334
445
  * Navigate to a path - auto-detects internal vs external.
335
446
  */
336
- navTo(t, e) {
337
- if (t.startsWith("http://") || t.startsWith("https://")) {
338
- this.redirect(t);
447
+ navTo(e, t) {
448
+ if (e.startsWith("http://") || e.startsWith("https://")) {
449
+ this.redirect(e);
339
450
  return;
340
451
  }
341
- this.navigate(t, e);
452
+ this.navigate(e, t);
342
453
  },
343
454
  /**
344
455
  * Update the iframe height.
345
456
  */
346
- resize(t) {
347
- if (typeof t != "number" || t < 0) {
348
- l(T.RESIZE, [
457
+ resize(e) {
458
+ if (typeof e != "number" || e < 0) {
459
+ f(y.RESIZE, [
349
460
  "Height must be a non-negative number"
350
461
  ]);
351
462
  return;
352
463
  }
353
- i(T.RESIZE, { height: t });
464
+ o(y.RESIZE, { height: e });
354
465
  },
355
466
  /**
356
467
  * Auto-resize iframe to content height.
357
468
  */
358
469
  autoResize() {
359
- const t = document.documentElement.scrollHeight;
360
- this.resize(t);
470
+ const e = document.documentElement.scrollHeight;
471
+ this.resize(e);
472
+ },
473
+ /**
474
+ * Set the page title in the host document.
475
+ */
476
+ setTitle(e) {
477
+ if (typeof e != "string" || !e.trim()) {
478
+ f(m.SET_TITLE, [
479
+ "Title must be a non-empty string"
480
+ ]);
481
+ return;
482
+ }
483
+ o(m.SET_TITLE, { title: e });
361
484
  }
362
485
  };
363
486
  }
364
- function ee() {
365
- const t = /* @__PURE__ */ new Set();
366
- return m(g.ACTION_CLICK, (e) => {
367
- t.forEach((r) => {
487
+ function pe() {
488
+ const e = /* @__PURE__ */ new Set();
489
+ let t = null;
490
+ return T(w.ACTION_CLICK, (r) => {
491
+ if (t)
368
492
  try {
369
- r(e.url, e.value);
493
+ t();
370
494
  } catch (n) {
371
- console.error("[EmbeddedSDK] Error in action click callback:", n);
495
+ u.error("Error in onClick callback:", n);
496
+ }
497
+ e.forEach((n) => {
498
+ try {
499
+ n(r.payload.url, r.payload.value);
500
+ } catch (a) {
501
+ u.error("Error in action click callback:", a);
372
502
  }
373
503
  });
374
504
  }), {
375
505
  /**
376
506
  * Set the primary action button.
377
507
  */
378
- setAction(e) {
379
- const r = X(e);
380
- if (!r.valid) {
381
- l(g.SET_ACTION, r.errors);
508
+ setAction(r) {
509
+ var a;
510
+ const n = he(r);
511
+ if (!n.valid) {
512
+ f(w.SET_ACTION, n.errors);
382
513
  return;
383
514
  }
384
- i(g.SET_ACTION, {
385
- title: e.title,
386
- url: e.url,
387
- value: e.value,
388
- extendedActions: e.extendedActions
515
+ r.onClick ? t = r.onClick : t = null, o(w.SET_ACTION, {
516
+ title: r.title,
517
+ onClick: r.onClick ? !0 : void 0,
518
+ value: r.value,
519
+ subTitle: r.subTitle,
520
+ icon: r.icon,
521
+ disabled: r.disabled,
522
+ extendedActions: (a = r.extendedActions) == null ? void 0 : a.map((l) => ({
523
+ title: l.title,
524
+ subTitle: l.subTitle,
525
+ url: l.url,
526
+ value: l.value,
527
+ icon: l.icon,
528
+ disabled: l.disabled
529
+ }))
389
530
  });
390
531
  },
391
532
  /**
392
533
  * Clear the primary action button.
393
534
  */
394
535
  clearAction() {
395
- i(g.SET_ACTION, {
536
+ t = null, o(w.SET_ACTION, {
396
537
  title: ""
397
538
  });
398
539
  },
399
540
  /**
400
541
  * Subscribe to action button clicks.
401
542
  */
402
- onActionClick(e) {
403
- return t.add(e), () => {
404
- t.delete(e);
543
+ onActionClick(r) {
544
+ return e.add(r), () => {
545
+ e.delete(r);
405
546
  };
406
547
  },
407
548
  // Legacy aliases
408
- primaryAction(e) {
409
- this.setAction(e);
549
+ primaryAction(r) {
550
+ this.setAction(r);
410
551
  },
411
552
  clearPrimaryAction() {
412
553
  this.clearAction();
413
554
  }
414
555
  };
415
556
  }
416
- function te() {
557
+ function be() {
417
558
  return {
418
559
  /**
419
560
  * Show loading indicator.
561
+ * @param mode - Display mode ('full' for full page, 'component' for inline)
420
562
  */
421
- show(t = "full") {
422
- i(o.LOADING, { status: !1, mode: t });
563
+ show(e = "full") {
564
+ o(d.LOADING, { status: !1, mode: e });
423
565
  },
424
566
  /**
425
567
  * Hide loading indicator.
426
568
  */
427
569
  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: [] });
570
+ o(d.LOADING, { status: !0, mode: "full" });
472
571
  }
473
572
  };
474
573
  }
475
- function ie() {
476
- const t = (e) => {
477
- const r = j(e);
478
- if (!r.valid) {
479
- l(o.TOAST, r.errors);
574
+ function Ee() {
575
+ const e = (t) => {
576
+ const i = ue(t);
577
+ if (!i.valid) {
578
+ f(d.TOAST, i.errors);
480
579
  return;
481
580
  }
482
- i(o.TOAST, {
483
- type: e.type,
484
- message: e.message,
485
- duration: e.duration
581
+ o(d.TOAST, {
582
+ type: t.type,
583
+ message: t.message,
584
+ duration: t.duration
486
585
  });
487
586
  };
488
587
  return {
489
588
  /**
490
589
  * Show a toast notification.
491
590
  */
492
- show: t,
591
+ show: e,
493
592
  /**
494
593
  * Show success toast.
495
594
  */
496
- success(e, r) {
497
- t({ type: "success", message: e, duration: r });
595
+ success(t, i) {
596
+ e({ type: "success", message: t, duration: i });
498
597
  },
499
598
  /**
500
599
  * Show error toast.
501
600
  */
502
- error(e, r) {
503
- t({ type: "error", message: e, duration: r });
601
+ error(t, i) {
602
+ e({ type: "error", message: t, duration: i });
504
603
  },
505
604
  /**
506
605
  * Show warning toast.
507
606
  */
508
- warning(e, r) {
509
- t({ type: "warning", message: e, duration: r });
607
+ warning(t, i) {
608
+ e({ type: "warning", message: t, duration: i });
510
609
  },
511
610
  /**
512
611
  * Show info toast.
513
612
  */
514
- info(e, r) {
515
- t({ type: "info", message: e, duration: r });
613
+ info(t, i) {
614
+ e({ type: "info", message: t, duration: i });
516
615
  }
517
616
  };
518
617
  }
519
- function se() {
618
+ function ye() {
520
619
  return {
521
620
  /**
522
621
  * Open a modal.
523
622
  */
524
- open(t, e) {
525
- i(o.MODAL, {
623
+ open(e, t) {
624
+ o(d.MODAL, {
526
625
  action: "open",
527
- id: t,
528
- content: e
626
+ id: e,
627
+ content: t
529
628
  });
530
629
  },
531
630
  /**
532
631
  * Close a modal.
533
632
  */
534
- close(t) {
535
- i(o.MODAL, {
633
+ close(e) {
634
+ o(d.MODAL, {
536
635
  action: "close",
537
- id: t
636
+ id: e
538
637
  });
539
638
  }
540
639
  };
541
640
  }
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(", "))));
641
+ function Te() {
642
+ return async (e) => {
643
+ const t = ge(e);
644
+ return t.valid ? ie(d.CONFIRM, {
645
+ title: e.title,
646
+ message: e.message,
647
+ confirmText: e.confirmText ?? "Confirm",
648
+ cancelText: e.cancelText ?? "Cancel",
649
+ variant: e.variant ?? "info"
650
+ }) : (f(d.CONFIRM, t.errors), Promise.reject(new Error(t.errors.join(", "))));
552
651
  };
553
652
  }
554
- function oe() {
653
+ function ve() {
555
654
  return {
556
- loading: te(),
557
- overlay: re(),
558
- breadcrumbs: ne(),
559
- toast: ie(),
560
- modal: se(),
561
- confirm: ae()
655
+ loading: be(),
656
+ toast: Ee(),
657
+ modal: ye(),
658
+ confirm: Te()
562
659
  };
563
660
  }
564
- function ue() {
661
+ function we() {
565
662
  return {
566
663
  /**
567
664
  * Create/initiate a checkout.
568
665
  */
569
- create(t) {
570
- const e = W(t);
571
- if (!e.valid) {
572
- l(w.CREATE, e.errors);
666
+ create(e) {
667
+ const t = ce(e);
668
+ if (!t.valid) {
669
+ f($.CREATE, t.errors);
573
670
  return;
574
671
  }
575
- i(w.CREATE, { payload: t });
672
+ o($.CREATE, e);
576
673
  }
577
674
  };
578
675
  }
579
- const I = {
580
- appId: "",
581
- env: "prod",
676
+ const U = {
582
677
  debug: !1,
583
678
  initialized: !1
584
- }, C = {
679
+ }, Ae = {
680
+ theme: "light",
681
+ width: 0,
682
+ locale: "ar",
683
+ currency: "SAR"
684
+ }, V = {
585
685
  ready: !1,
586
- initializing: !1
686
+ initializing: !1,
687
+ layout: { ...Ae }
587
688
  };
588
- class le {
689
+ class Se {
589
690
  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();
691
+ this.config = { ...U }, this.state = { ...V }, this.themeCallbacks = /* @__PURE__ */ new Set(), this.initCallbacks = /* @__PURE__ */ new Set(), this.appReady = !1, this.auth = le(), this.page = me(), this.nav = pe(), this.ui = ve(), this.checkout = we(), this.setupThemeListener(), this.setupResponseListeners();
591
692
  }
592
693
  /**
593
- * Get current SDK state.
694
+ * Get current SDK state (layout info only, no token).
594
695
  */
595
696
  getState() {
596
- return { ...this.state };
697
+ return {
698
+ ready: this.state.ready,
699
+ initializing: this.state.initializing,
700
+ layout: { ...this.state.layout }
701
+ };
597
702
  }
598
703
  /**
599
704
  * Get current SDK configuration.
@@ -602,33 +707,46 @@ class le {
602
707
  return { ...this.config };
603
708
  }
604
709
  /**
605
- * Check if SDK is ready.
710
+ * Check if SDK is initialized.
606
711
  */
607
712
  isReady() {
608
713
  return this.state.ready;
609
714
  }
610
715
  /**
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.
716
+ * Unified internal logging function that supports all console log types.
717
+ *
718
+ * @param type - Log type (log, warn, error, info, debug)
719
+ * @param args - Arguments to log
618
720
  */
619
- warn(...e) {
620
- console.warn(`[EmbeddedSDK v${p}]`, ...e);
721
+ internalLog(t, ...i) {
722
+ switch (t) {
723
+ case "log":
724
+ u.log(...i);
725
+ break;
726
+ case "warn":
727
+ u.warn(...i);
728
+ break;
729
+ case "error":
730
+ u.error(...i);
731
+ break;
732
+ case "info":
733
+ u.info(...i);
734
+ break;
735
+ case "debug":
736
+ u.debug(...i);
737
+ break;
738
+ }
621
739
  }
622
740
  /**
623
741
  * Set up listener for theme changes from host.
624
742
  */
625
743
  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) => {
744
+ T(k.THEME_CHANGE, (t) => {
745
+ this.state.layout.theme = t.payload.theme, this.internalLog("debug", "Theme changed:", t.payload.theme), this.themeCallbacks.forEach((i) => {
628
746
  try {
629
- r(e.dark);
630
- } catch (n) {
631
- console.error("[EmbeddedSDK] Error in theme callback:", n);
747
+ i(t.payload.theme);
748
+ } catch (r) {
749
+ this.internalLog("error", "Error in theme callback:", r);
632
750
  }
633
751
  });
634
752
  });
@@ -637,10 +755,10 @@ class le {
637
755
  * Set up listeners for async response events from host.
638
756
  */
639
757
  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);
758
+ T(d.CONFIRM_RESPONSE, (t) => {
759
+ this.internalLog("debug", "Received confirm response:", t), t.requestId && D(t.requestId, { confirmed: t.payload.confirmed });
760
+ }), T(d.MODAL_RESPONSE, (t) => {
761
+ this.internalLog("debug", "Received modal response:", t), t.requestId && D(t.requestId, t.payload.result, t.payload.error);
644
762
  });
645
763
  }
646
764
  /**
@@ -651,127 +769,187 @@ class le {
651
769
  *
652
770
  * @example
653
771
  * ```typescript
654
- * const unsubscribe = embedded.onThemeChange((isDark) => {
655
- * document.body.classList.toggle('dark-mode', isDark);
772
+ * const unsubscribe = embedded.onThemeChange((theme) => {
773
+ * document.body.classList.toggle('dark-mode', theme === 'dark');
656
774
  * });
657
775
  * ```
658
776
  */
659
- onThemeChange(e) {
660
- return this.themeCallbacks.add(e), () => {
661
- this.themeCallbacks.delete(e);
777
+ onThemeChange(t) {
778
+ return this.themeCallbacks.add(t), () => {
779
+ this.themeCallbacks.delete(t);
662
780
  };
663
781
  }
664
782
  /**
665
- * Report an error to the host.
783
+ * Subscribe to init completion. If called after init, fires immediately.
666
784
  *
667
- * @param error - Error object or message
668
- * @param context - Additional context
785
+ * @param callback - Function called when init completes
786
+ * @returns Unsubscribe function
669
787
  *
670
788
  * @example
671
789
  * ```typescript
672
- * try {
673
- * await riskyOperation();
674
- * } catch (err) {
675
- * embedded.reportError(err, { operation: 'riskyOperation' });
676
- * }
790
+ * embedded.onInit((state) => {
791
+ * console.log('SDK initialized with layout:', state.layout);
792
+ * });
677
793
  * ```
678
794
  */
679
- reportError(e, r) {
680
- const n = typeof e == "string" ? { message: e } : {
681
- message: e.message,
682
- stack: e.stack,
683
- code: e.code
795
+ onInit(t) {
796
+ if (this.config.initialized)
797
+ try {
798
+ t(this.getState());
799
+ } catch (i) {
800
+ this.internalLog("error", "Error in init callback:", i);
801
+ }
802
+ return this.initCallbacks.add(t), () => {
803
+ this.initCallbacks.delete(t);
684
804
  };
685
- i(L.REPORT, {
686
- error: n,
805
+ }
806
+ /**
807
+ * Send log message to host for debugging/monitoring.
808
+ *
809
+ * @param level - Log level (info, warn, error)
810
+ * @param message - Log message
811
+ * @param context - Additional context
812
+ *
813
+ * @example
814
+ * ```typescript
815
+ * embedded.log('error', 'Failed to load data', { endpoint: '/api/data' });
816
+ * ```
817
+ */
818
+ log(t, i, r) {
819
+ o(j.LOG, {
820
+ level: t,
821
+ message: i,
687
822
  context: r
688
823
  });
689
824
  }
825
+ /**
826
+ * Signal that the app is fully loaded and ready.
827
+ * This removes the host's loading overlay.
828
+ *
829
+ * @example
830
+ * ```typescript
831
+ * // After verifying token and loading initial data
832
+ * embedded.ready();
833
+ * ```
834
+ */
835
+ ready() {
836
+ if (this.appReady) {
837
+ this.internalLog("debug", "App already signaled as ready");
838
+ return;
839
+ }
840
+ if (!this.config.initialized) {
841
+ this.internalLog("warn", "Cannot signal ready before init() is called");
842
+ return;
843
+ }
844
+ this.appReady = !0, o(y.READY, {}), this.internalLog("debug", "Sent ready signal to host");
845
+ }
690
846
  /**
691
847
  * Initialize the SDK and establish connection with the host.
692
848
  *
693
- * @param options - Initialization options
694
- * @returns Promise that resolves when SDK is ready
849
+ * @param options - Initialization options (optional)
850
+ * @returns Promise that resolves with layout info
695
851
  *
696
852
  * @example
697
853
  * ```typescript
698
- * await embedded.init({
699
- * app_id: 'my-app-123',
700
- * env: 'prod',
701
- * debug: true
702
- * });
854
+ * const { layout } = await embedded.init({ debug: true });
855
+ * console.log('Theme:', layout.theme);
856
+ * console.log('Locale:', layout.locale);
703
857
  * ```
704
858
  */
705
- async init(e) {
859
+ async init(t = {}) {
706
860
  if (this.config.initialized)
707
- return this.log("Already initialized, returning current state"), this.getState();
861
+ return this.internalLog(
862
+ "debug",
863
+ "Already initialized, returning current layout"
864
+ ), { layout: { ...this.state.layout } };
708
865
  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,
866
+ return this.internalLog("warn", "Initialization already in progress"), this.waitForInit();
867
+ ee() || this.internalLog(
868
+ "warn",
869
+ "Not running in an iframe. Some features may not work."
870
+ ), this.config = {
871
+ debug: t.debug ?? !1,
716
872
  initialized: !1
717
- }, this.state.initializing = !0, this.log("Initializing with options:", e);
873
+ }, W({
874
+ debug: this.config.debug
875
+ }), this.state.initializing = !0, this.internalLog("debug", "Initializing SDK...");
718
876
  try {
719
- i(T.READY, {
877
+ o(y.INIT, {
720
878
  height: document.documentElement.scrollHeight
721
- }), this.log("Sent iframe.ready message, waiting for context...");
722
- const r = await V(
723
- y.PROVIDE
879
+ }), this.internalLog(
880
+ "debug",
881
+ "Sent iframe.ready message, waiting for context..."
882
+ );
883
+ const i = await J(
884
+ k.PROVIDE
724
885
  );
725
- return this.log("Received context from host:", r), this.state = {
886
+ this.internalLog("debug", "Received context from host:", i);
887
+ const r = i.payload.layout;
888
+ this.state = {
726
889
  ready: !0,
727
890
  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;
891
+ layout: {
892
+ theme: (r == null ? void 0 : r.theme) ?? "light",
893
+ width: (r == null ? void 0 : r.width) ?? 0,
894
+ locale: (r == null ? void 0 : r.locale) ?? "ar",
895
+ currency: (r == null ? void 0 : r.currency) ?? "SAR"
896
+ }
897
+ }, this.config.initialized = !0, this.internalLog(
898
+ "debug",
899
+ "Initialization complete. Layout:",
900
+ this.state.layout
901
+ );
902
+ const n = this.getState();
903
+ return this.initCallbacks.forEach((a) => {
904
+ try {
905
+ a(n);
906
+ } catch (l) {
907
+ this.internalLog("error", "Error in init callback:", l);
908
+ }
909
+ }), { layout: { ...this.state.layout } };
910
+ } catch (i) {
911
+ throw this.state.initializing = !1, this.state.ready = !1, i;
740
912
  }
741
913
  }
742
914
  /**
743
- * Wait for the SDK to be ready.
915
+ * Wait for initialization to complete.
744
916
  * Useful when multiple calls to init() might happen.
745
917
  */
746
- waitForReady() {
747
- return new Promise((e) => {
748
- const r = () => {
749
- this.state.ready ? e(this.getState()) : setTimeout(r, 100);
750
- };
751
- r();
918
+ waitForInit() {
919
+ return new Promise((t) => {
920
+ const i = this.onInit((r) => {
921
+ i(), t({ layout: { ...r.layout } });
922
+ });
752
923
  });
753
924
  }
754
925
  /**
755
926
  * Destroy the SDK instance and clean up resources.
927
+ * Sends a destroy event to the host to navigate away from the embedded view.
928
+ *
929
+ * @example
930
+ * ```typescript
931
+ * // On auth failure or when app needs to exit
932
+ * embedded.destroy();
933
+ * ```
756
934
  */
757
935
  destroy() {
758
- this.log("Destroying SDK instance"), B("SDK destroyed"), P(), this.themeCallbacks.clear(), this.config = { ...I }, this.state = { ...C };
936
+ this.internalLog("debug", "Destroying SDK instance"), this.config.initialized && (o(y.DESTROY, {}), this.internalLog("debug", "Sent destroy event to host")), ne("SDK destroyed"), Q(), this.themeCallbacks.clear(), this.initCallbacks.clear(), this.config = { ...U }, this.state = { ...V }, this.appReady = !1;
759
937
  }
760
938
  }
761
- let f = null;
762
- function ce() {
763
- return f || (f = new le()), f;
939
+ let p = null;
940
+ function F() {
941
+ return p || (p = new Se()), p;
764
942
  }
765
- function fe() {
766
- f && (f.destroy(), f = null);
943
+ function Re() {
944
+ p && (p.destroy(), p = null);
767
945
  }
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));
946
+ const q = F(), Ce = L;
947
+ typeof window < "u" && (window.salla = window.salla || window.Salla || {}, window.Salla = window.salla, window.salla.embedded || (window.salla.embedded = q), window.Salla.embedded || (window.Salla.embedded = q));
770
948
  export {
771
- le as EmbeddedApp,
772
- N as embedded,
773
- ce as getEmbeddedApp,
774
- fe as resetEmbeddedApp,
775
- me as version
949
+ Se as EmbeddedApp,
950
+ q as embedded,
951
+ F as getEmbeddedApp,
952
+ Re as resetEmbeddedApp,
953
+ Ce as version
776
954
  };
777
955
  //# sourceMappingURL=index.js.map