@salla.sa/embedded-sdk 0.2.2 → 0.2.4

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