@salla.sa/embedded-sdk 0.2.2 → 0.2.3

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