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

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