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