@salla.sa/embedded-sdk 0.1.0-beta.2 → 0.1.0-beta.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/README.md CHANGED
@@ -42,10 +42,9 @@ async function bootstrap() {
42
42
 
43
43
  // 4. Set up your app
44
44
  embedded.page.setTitle("My App");
45
-
46
45
  } catch (err) {
47
- // Signal auth error (redirects to apps page with error toast)
48
- embedded.auth.error(err.message);
46
+ // Exit embedded view (navigates to apps page)
47
+ embedded.destroy();
49
48
  }
50
49
  }
51
50
 
@@ -58,14 +57,13 @@ bootstrap();
58
57
  <script src="https://unpkg.com/@salla.sa/embedded-sdk/dist/index.umd.js"></script>
59
58
  <script>
60
59
  const embedded = SallaEmbeddedSDK.embedded;
61
-
62
- embedded.init({ debug: true })
63
- .then(function(result) {
64
- console.log("Layout:", result.layout);
65
-
66
- const token = embedded.auth.getToken();
67
- // ... verify token and call embedded.ready()
68
- });
60
+
61
+ embedded.init({ debug: true }).then(function (result) {
62
+ console.log("Layout:", result.layout);
63
+
64
+ const token = embedded.auth.getToken();
65
+ // ... verify token and call embedded.ready()
66
+ });
69
67
  </script>
70
68
  ```
71
69
 
@@ -86,7 +84,7 @@ The SDK is also accessible via the global `Salla` object:
86
84
 
87
85
  ```typescript
88
86
  const { layout } = await embedded.init({
89
- debug: false, // Optional: Enable debug logging
87
+ debug: false, // Optional: Enable debug logging
90
88
  });
91
89
  ```
92
90
 
@@ -94,7 +92,7 @@ Returns layout information from the host:
94
92
 
95
93
  ```typescript
96
94
  interface LayoutInfo {
97
- theme: 'light' | 'dark';
95
+ theme: "light" | "dark";
98
96
  width: number;
99
97
  locale: string;
100
98
  currency: string;
@@ -115,11 +113,11 @@ const ready = embedded.isReady();
115
113
 
116
114
  // Subscribe to initialization
117
115
  embedded.onInit((state) => {
118
- console.log('Initialized with layout:', state.layout);
116
+ console.log("Initialized with layout:", state.layout);
119
117
  });
120
118
 
121
119
  // Send log message to host
122
- embedded.log('error', 'Something failed', { context: 'data' });
120
+ embedded.log("error", "Something failed", { context: "data" });
123
121
  ```
124
122
 
125
123
  ### Auth Module
@@ -128,34 +126,31 @@ embedded.log('error', 'Something failed', { context: 'data' });
128
126
  // Get token from URL (?token=XXX)
129
127
  const token = embedded.auth.getToken();
130
128
 
131
- // Request logout (navigates to apps page)
132
- embedded.auth.logout();
133
-
134
129
  // Request token refresh (re-renders iframe with new token)
135
130
  embedded.auth.refresh();
131
+ ```
136
132
 
137
- // Signal auth error (navigates away with error toast)
138
- embedded.auth.error("Token verification failed");
133
+ ### Destroy
134
+
135
+ ```typescript
136
+ // Exit embedded view and navigate back to app page
137
+ embedded.destroy();
139
138
  ```
140
139
 
141
140
  ### UI Module
142
141
 
143
142
  ```typescript
144
143
  // Loading (in-app loading states)
145
- embedded.ui.loading.show(); // Show loading
146
- embedded.ui.loading.show("component"); // Component-level
147
- embedded.ui.loading.hide(); // Hide loading
148
-
149
- // Overlay (fullscreen mode)
150
- embedded.ui.overlay.open();
151
- embedded.ui.overlay.close();
144
+ embedded.ui.loading.show(); // Show loading
145
+ embedded.ui.loading.show("component"); // Component-level
146
+ embedded.ui.loading.hide(); // Hide loading
152
147
 
153
148
  // Toast Notifications
154
149
  embedded.ui.toast.success("Product saved!");
155
150
  embedded.ui.toast.error("Something went wrong");
156
151
  embedded.ui.toast.warning("Please review input");
157
152
  embedded.ui.toast.info("New features available");
158
- embedded.ui.toast.success("Saved!", 5000); // Custom duration
153
+ embedded.ui.toast.success("Saved!", 5000); // Custom duration
159
154
 
160
155
  // Generic toast
161
156
  embedded.ui.toast.show({
@@ -174,7 +169,7 @@ const result = await embedded.ui.confirm({
174
169
  message: "This action cannot be undone.",
175
170
  confirmText: "Delete",
176
171
  cancelText: "Cancel",
177
- variant: "danger", // 'danger' | 'warning' | 'info'
172
+ variant: "danger", // 'danger' | 'warning' | 'info'
178
173
  });
179
174
 
180
175
  if (result.confirmed) {
@@ -202,22 +197,39 @@ embedded.page.navTo("https://external.com");
202
197
 
203
198
  // Iframe Resize
204
199
  embedded.page.resize(800);
205
- embedded.page.autoResize(); // Auto-detect content height
200
+ embedded.page.autoResize(); // Auto-detect content height
206
201
  ```
207
202
 
208
203
  ### Nav Module
209
204
 
210
205
  ```typescript
211
- // Set primary action button
206
+ // Set primary action button with onClick
212
207
  embedded.nav.setAction({
213
208
  title: "Create Product",
214
- url: "/products/new",
209
+ onClick: () => {
210
+ // Handle click
211
+ console.log("Create product clicked");
212
+ },
213
+ });
214
+
215
+ // With optional props
216
+ embedded.nav.setAction({
217
+ title: "Save",
218
+ subTitle: "Save changes",
219
+ icon: "sicon-save",
220
+ disabled: false,
221
+ onClick: () => {
222
+ handleSave();
223
+ },
215
224
  });
216
225
 
217
226
  // With dropdown actions
218
227
  embedded.nav.setAction({
219
228
  title: "Actions",
220
229
  value: "main",
230
+ onClick: () => {
231
+ // Handle main action click
232
+ },
221
233
  extendedActions: [
222
234
  { title: "Import", url: "/import" },
223
235
  { title: "Export", value: "export" },
package/dist/cjs/index.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const k="0.1.0-beta.2",x={version:k},n="embedded::",y={INIT:`${n}iframe.ready`,RESIZE:`${n}iframe.resize`,READY:`${n}ready`},A={PROVIDE:`${n}context.provide`,THEME_CHANGE:`${n}theme.change`},V={LOG:`${n}log`},b={LOGOUT:`${n}auth.logout`,REFRESH:`${n}auth.refresh`,ERROR:`${n}auth.error`},h={NAVIGATE:`${n}page.navigate`,REDIRECT:`${n}page.redirect`,SET_TITLE:`${n}page.setTitle`},E={SET_ACTION:`${n}nav.setAction`,ACTION_CLICK:`${n}nav.actionClick`},l={LOADING:`${n}ui.loading`,OVERLAY:`${n}ui.overlay`,TOAST:`${n}ui.toast`,MODAL:`${n}ui.modal`,CONFIRM:`${n}ui.confirm`,CONFIRM_RESPONSE:`${n}ui.confirm.response`,MODAL_RESPONSE:`${n}ui.modal.response`},S={CREATE:`${n}checkout.create`},v=x.version,U=1e4,z=["localhost","merchants.workers.dev","s.salla.sa",".salla.group",".salla.sa"];function K(t){try{const i=new URL(t).hostname;return z.some(r=>r.startsWith(".")?i.endsWith(r)||i===r.slice(1):i===r||i.startsWith(`${r}:`))}catch{return!1}}function F(){return typeof window>"u"||window.parent===window?null:window.parent}function s(t,e,i="*"){const r=F();if(!r){console.warn("[EmbeddedSDK] Not running in an iframe, cannot post to host");return}const a={event:t,...e};r.postMessage(a,i)}const d=new Map;let T=!1;function O(t){if(process.env.NODE_ENV==="production"&&!K(t.origin))return;const e=t.data;if(!e||typeof e.event!="string")return;const i=d.get(e.event);i&&i.forEach(a=>{try{a(e)}catch(o){console.error("[EmbeddedSDK] Error in message handler:",o)}});const r=d.get("*");r&&r.forEach(a=>{try{a(e)}catch(o){console.error("[EmbeddedSDK] Error in wildcard handler:",o)}})}function P(){T||typeof window>"u"||(window.addEventListener("message",O),T=!0)}function g(t,e){P(),d.has(t)||d.set(t,new Set);const i=d.get(t);return i.add(e),()=>{i.delete(e),i.size===0&&d.delete(t)}}function q(t,e=U){return new Promise((i,r)=>{const a=setTimeout(()=>{o(),r(new Error(`[EmbeddedSDK] Timeout waiting for "${t}" message`))},e),o=g(t,u=>{clearTimeout(a),o(),i(u)})})}function G(){d.clear(),T&&typeof window<"u"&&(window.removeEventListener("message",O),T=!1)}function H(){return typeof window>"u"?!1:window.parent!==window}const f=new Map,j=3e4;function Y(){const t=Date.now(),e=Math.random().toString(36).slice(2,9);return`req_${t}_${e}`}function W(t,e={},i=j){const r=Y();return new Promise((a,o)=>{const u=setTimeout(()=>{f.get(r)&&(f.delete(r),o(new Error(`[EmbeddedSDK] Request "${t}" timed out after ${i}ms`)))},i);f.set(r,{resolve:a,reject:o,timeout:u,event:t}),s(t,{...e,requestId:r})})}function R(t,e,i){const r=f.get(t);if(!r){console.warn(`[EmbeddedSDK] Received response for unknown request: ${t}`);return}clearTimeout(r.timeout),f.delete(t),i?r.reject(new Error(i)):r.resolve(e)}function Z(t="SDK cleanup"){f.forEach((e,i)=>{clearTimeout(e.timeout),e.reject(new Error(`[EmbeddedSDK] Request ${i} cancelled: ${t}`))}),f.clear()}function X(t){return{getToken(){return new URLSearchParams(window.location.search).get("token")},logout(){s(b.LOGOUT,{})},refresh(){s(b.REFRESH,{})},error(e){s(b.ERROR,{message:e})}}}const C=["success","error","warning","info"];function Q(t){const e=[];return t.type===void 0||t.type===null?e.push("Toast type is required"):(typeof t.type!="string"||!C.includes(t.type))&&e.push(`Invalid toast type "${t.type}". Expected: ${C.join(" | ")}`),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}}function B(t){const e=[];return typeof t!="object"||t===null?(e.push("Checkout payload must be an object"),{valid:!1,errors:e}):(t.amount!==void 0&&t.amount!==null&&(typeof t.amount!="number"?e.push("Checkout amount must be a number"):t.amount<0&&e.push("Checkout amount cannot be negative")),t.currency!==void 0&&t.currency!==null&&(typeof t.currency!="string"?e.push("Checkout currency must be a string"):t.currency.trim()===""&&e.push("Checkout currency cannot be empty")),t.items!==void 0&&t.items!==null&&(Array.isArray(t.items)||e.push("Checkout items must be an array")),{valid:e.length===0,errors:e})}function J(t){const e=[];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}}function ee(t){const e=[];if(t.url===void 0||t.url===null)e.push("Redirect URL is required");else if(typeof t.url!="string")e.push("Redirect URL must be a string");else if(t.url.trim()==="")e.push("Redirect URL cannot be empty");else try{new URL(t.url)}catch{e.push(`Invalid redirect URL: "${t.url}"`)}return{valid:e.length===0,errors:e}}function te(t){const e=[];return t.title===void 0||t.title===null?e.push("Nav action title is required"):typeof t.title!="string"&&e.push("Nav action title must be a string"),t.url!==void 0&&t.url!==null&&typeof t.url!="string"&&e.push("Nav action URL must be a string"),t.value!==void 0&&t.value!==null&&typeof t.value!="string"&&e.push("Nav action value must be a string"),t.extendedActions!==void 0&&t.extendedActions!==null&&(Array.isArray(t.extendedActions)?t.extendedActions.forEach((i,r)=>{if(typeof i!="object"||i===null){e.push(`Extended action at index ${r} must be an object`);return}const a=i;(!a.title||typeof a.title!="string")&&e.push(`Extended action at index ${r} is missing required "title" property`)}):e.push("Nav action extendedActions must be an array")),{valid:e.length===0,errors:e}}const L=["danger","warning","info"];function ie(t){const e=[];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"||!L.includes(t.variant))&&e.push(`Invalid confirm variant "${t.variant}". Expected: ${L.join(" | ")}`),{valid:e.length===0,errors:e}}function c(t,e){console.error(`[EmbeddedSDK] Validation failed for ${t}:
2
- `+e.map(i=>` • ${i}`).join(`
3
- `))}function re(){return{navigate(t,e){const i=J({path:t,...e});if(!i.valid){c(h.NAVIGATE,i.errors);return}s(h.NAVIGATE,{path:t,state:e==null?void 0:e.state,replace:e==null?void 0:e.replace})},redirect(t){const e=ee({url:t});if(!e.valid){c(h.REDIRECT,e.errors);return}s(h.REDIRECT,{url:t})},navTo(t,e){if(t.startsWith("http://")||t.startsWith("https://")){this.redirect(t);return}this.navigate(t,e)},resize(t){if(typeof t!="number"||t<0){c(y.RESIZE,["Height must be a non-negative number"]);return}s(y.RESIZE,{height:t})},autoResize(){const t=document.documentElement.scrollHeight;this.resize(t)},setTitle(t){if(typeof t!="string"||!t.trim()){c(h.SET_TITLE,["Title must be a non-empty string"]);return}s(h.SET_TITLE,{title:t})}}}function ne(){const t=new Set;return g(E.ACTION_CLICK,e=>{t.forEach(i=>{try{i(e.url,e.value)}catch(r){console.error("[EmbeddedSDK] Error in action click callback:",r)}})}),{setAction(e){const i=te(e);if(!i.valid){c(E.SET_ACTION,i.errors);return}s(E.SET_ACTION,{title:e.title,url:e.url,value:e.value,extendedActions:e.extendedActions})},clearAction(){s(E.SET_ACTION,{title:""})},onActionClick(e){return t.add(e),()=>{t.delete(e)}},primaryAction(e){this.setAction(e)},clearPrimaryAction(){this.clearAction()}}}function se(){return{show(t="full"){s(l.LOADING,{status:!1,mode:t})},hide(){s(l.LOADING,{status:!0,mode:"full"})}}}function ae(){return{open(){s(l.OVERLAY,{action:"open"})},close(){s(l.OVERLAY,{action:"close"})}}}function oe(){const t=e=>{const i=Q(e);if(!i.valid){c(l.TOAST,i.errors);return}s(l.TOAST,{type:e.type,message:e.message,duration:e.duration})};return{show:t,success(e,i){t({type:"success",message:e,duration:i})},error(e,i){t({type:"error",message:e,duration:i})},warning(e,i){t({type:"warning",message:e,duration:i})},info(e,i){t({type:"info",message:e,duration:i})}}}function le(){return{open(t,e){s(l.MODAL,{action:"open",id:t,content:e})},close(t){s(l.MODAL,{action:"close",id:t})}}}function ue(){return async t=>{const e=ie(t);return e.valid?W(l.CONFIRM,{title:t.title,message:t.message,confirmText:t.confirmText??"Confirm",cancelText:t.cancelText??"Cancel",variant:t.variant??"info"}):(c(l.CONFIRM,e.errors),Promise.reject(new Error(e.errors.join(", "))))}}function ce(){return{loading:se(),overlay:ae(),toast:oe(),modal:le(),confirm:ue()}}function de(){return{create(t){const e=B(t);if(!e.valid){c(S.CREATE,e.errors);return}s(S.CREATE,{payload:t})}}}const I={debug:!1,initialized:!1},fe={theme:"light",width:0,locale:"ar",currency:"SAR"},N={ready:!1,initializing:!1,layout:{...fe}};class D{constructor(){this.config={...I},this.state={...N},this.themeCallbacks=new Set,this.initCallbacks=new Set,this.appReady=!1,this.auth=X(),this.page=re(),this.nav=ne(),this.ui=ce(),this.checkout=de(),this.setupThemeListener(),this.setupResponseListeners()}getState(){return{ready:this.state.ready,initializing:this.state.initializing,layout:{...this.state.layout}}}getConfig(){return{...this.config}}isReady(){return this.state.ready}debugLog(...e){this.config.debug&&console.log(`[EmbeddedSDK v${v}]`,...e)}warn(...e){console.warn(`[EmbeddedSDK v${v}]`,...e)}setupThemeListener(){g(A.THEME_CHANGE,e=>{this.state.layout.theme=e.theme,this.debugLog("Theme changed:",e.theme),this.themeCallbacks.forEach(i=>{try{i(e.theme)}catch(r){console.error("[EmbeddedSDK] Error in theme callback:",r)}})})}setupResponseListeners(){g(l.CONFIRM_RESPONSE,e=>{this.debugLog("Received confirm response:",e),R(e.requestId,{confirmed:e.confirmed})}),g(l.MODAL_RESPONSE,e=>{this.debugLog("Received modal response:",e),R(e.requestId,e.result,e.error)})}onThemeChange(e){return this.themeCallbacks.add(e),()=>{this.themeCallbacks.delete(e)}}onInit(e){if(this.config.initialized)try{e(this.getState())}catch(i){console.error("[EmbeddedSDK] Error in init callback:",i)}return this.initCallbacks.add(e),()=>{this.initCallbacks.delete(e)}}log(e,i,r){s(V.LOG,{level:e,message:i,context:r})}ready(){if(this.appReady){this.debugLog("App already signaled as ready");return}if(!this.config.initialized){this.warn("Cannot signal ready before init() is called");return}this.appReady=!0,s(y.READY,{}),this.debugLog("Sent ready signal to host")}async init(e={}){var i,r,a,o;if(this.config.initialized)return this.debugLog("Already initialized, returning current layout"),{layout:{...this.state.layout}};if(this.state.initializing)return this.warn("Initialization already in progress"),this.waitForInit();H()||this.warn("Not running in an iframe. Some features may not work."),this.config={debug:e.debug??!1,initialized:!1},this.state.initializing=!0,this.debugLog("Initializing SDK...");try{s(y.INIT,{height:document.documentElement.scrollHeight}),this.debugLog("Sent iframe.ready message, waiting for context...");const u=await q(A.PROVIDE);this.debugLog("Received context from host:",u),this.state={ready:!0,initializing:!1,layout:{theme:((i=u.layout)==null?void 0:i.theme)??"light",width:((r=u.layout)==null?void 0:r.width)??0,locale:((a=u.layout)==null?void 0:a.locale)??"ar",currency:((o=u.layout)==null?void 0:o.currency)??"SAR"}},this.config.initialized=!0,this.debugLog("Initialization complete. Layout:",this.state.layout);const p=this.getState();return this.initCallbacks.forEach(_=>{try{_(p)}catch(M){console.error("[EmbeddedSDK] Error in init callback:",M)}}),{layout:{...this.state.layout}}}catch(u){throw this.state.initializing=!1,this.state.ready=!1,u}}waitForInit(){return new Promise(e=>{const i=()=>{this.state.ready?e({layout:{...this.state.layout}}):setTimeout(i,100)};i()})}destroy(){this.debugLog("Destroying SDK instance"),Z("SDK destroyed"),G(),this.themeCallbacks.clear(),this.initCallbacks.clear(),this.config={...I},this.state={...N},this.appReady=!1}}let m=null;function $(){return m||(m=new D),m}function he(){m&&(m.destroy(),m=null)}const w=$(),me=v;typeof window<"u"&&(window.salla=window.salla||window.Salla||{},window.Salla=window.salla,window.salla.embedded||(window.salla.embedded=w),window.Salla.embedded||(window.Salla.embedded=w));exports.EmbeddedApp=D;exports.embedded=w;exports.getEmbeddedApp=$;exports.resetEmbeddedApp=he;exports.version=me;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _="0.1.0-beta.4",M={version:_},s="embedded::",g={INIT:`${s}iframe.ready`,RESIZE:`${s}iframe.resize`,READY:`${s}ready`,DESTROY:`${s}destroy`},p={PROVIDE:`${s}context.provide`,THEME_CHANGE:`${s}theme.change`},x={LOG:`${s}log`},z={REFRESH:`${s}auth.refresh`},h={NAVIGATE:`${s}page.navigate`,REDIRECT:`${s}page.redirect`,SET_TITLE:`${s}page.setTitle`},b={SET_ACTION:`${s}nav.setAction`,ACTION_CLICK:`${s}nav.actionClick`},u={LOADING:`${s}ui.loading`,TOAST:`${s}ui.toast`,MODAL:`${s}ui.modal`,CONFIRM:`${s}ui.confirm`,CONFIRM_RESPONSE:`${s}ui.confirm.response`,MODAL_RESPONSE:`${s}ui.modal.response`},S={CREATE:`${s}checkout.create`},y=M.version,K=1e4,V=["localhost","merchants.workers.dev","s.salla.sa",".salla.group",".salla.sa"];function U(e){try{const n=new URL(e).hostname;return V.some(i=>i.startsWith(".")?n.endsWith(i)||n===i.slice(1):n===i||n.startsWith(`${i}:`))}catch{return!1}}function F(){return typeof window>"u"||window.parent===window?null:window.parent}function o(e,t,n="*"){const i=F();if(!i){console.warn("[EmbeddedSDK] Not running in an iframe, cannot post to host");return}const r={event:e,...t};i.postMessage(r,n)}const d=new Map;let T=!1;function L(e){if(process.env.NODE_ENV==="production"&&!U(e.origin))return;const t=e.data;if(!t||typeof t.event!="string")return;const n=d.get(t.event);n&&n.forEach(r=>{try{r(t)}catch(l){console.error("[EmbeddedSDK] Error in message handler:",l)}});const i=d.get("*");i&&i.forEach(r=>{try{r(t)}catch(l){console.error("[EmbeddedSDK] Error in wildcard handler:",l)}})}function P(){T||typeof window>"u"||(window.addEventListener("message",L),T=!0)}function E(e,t){P(),d.has(e)||d.set(e,new Set);const n=d.get(e);return n.add(t),()=>{n.delete(t),n.size===0&&d.delete(e)}}function q(e,t=K){return new Promise((n,i)=>{const r=setTimeout(()=>{l(),i(new Error(`[EmbeddedSDK] Timeout waiting for "${e}" message`))},t),l=E(e,a=>{clearTimeout(r),l(),n(a)})})}function G(){d.clear(),T&&typeof window<"u"&&(window.removeEventListener("message",L),T=!1)}function H(){return typeof window>"u"?!1:window.parent!==window}const f=new Map,j=3e4;function W(){const e=Date.now(),t=Math.random().toString(36).slice(2,9);return`req_${e}_${t}`}function Y(e,t={},n=j){const i=W();return new Promise((r,l)=>{const a=setTimeout(()=>{f.get(i)&&(f.delete(i),l(new Error(`[EmbeddedSDK] Request "${e}" timed out after ${n}ms`)))},n);f.set(i,{resolve:r,reject:l,timeout:a,event:e}),o(e,{...t,requestId:i})})}function A(e,t,n){const i=f.get(e);if(!i){console.warn(`[EmbeddedSDK] Received response for unknown request: ${e}`);return}clearTimeout(i.timeout),f.delete(e),n?i.reject(new Error(n)):i.resolve(t)}function Z(e="SDK cleanup"){f.forEach((t,n)=>{clearTimeout(t.timeout),t.reject(new Error(`[EmbeddedSDK] Request ${n} cancelled: ${e}`))}),f.clear()}function X(e){return{getToken(){return new URLSearchParams(window.location.search).get("token")},refresh(){o(z.REFRESH,{})}}}const C=["success","error","warning","info"];function Q(e){const t=[];return e.type===void 0||e.type===null?t.push("Toast type is required"):(typeof e.type!="string"||!C.includes(e.type))&&t.push(`Invalid toast type "${e.type}". Expected: ${C.join(" | ")}`),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}}function B(e){const t=[];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})}function J(e){const t=[];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}}function ee(e){const t=[];if(e.url===void 0||e.url===null)t.push("Redirect URL is required");else if(typeof e.url!="string")t.push("Redirect URL must be a string");else if(e.url.trim()==="")t.push("Redirect URL cannot be empty");else try{new URL(e.url)}catch{t.push(`Invalid redirect URL: "${e.url}"`)}return{valid:t.length===0,errors:t}}function te(e){const t=[];return e.title===void 0||e.title===null?t.push("Nav action title is required"):typeof e.title!="string"&&t.push("Nav action title must be a string"),e.onClick!==void 0&&e.onClick!==null&&typeof e.onClick!="function"&&t.push("Nav action onClick must be a function"),e.value!==void 0&&e.value!==null&&typeof e.value!="string"&&t.push("Nav action value must be a string"),e.subTitle!==void 0&&e.subTitle!==null&&typeof e.subTitle!="string"&&t.push("Nav action subTitle must be a string"),e.icon!==void 0&&e.icon!==null&&typeof e.icon!="string"&&t.push("Nav action icon must be a string"),e.disabled!==void 0&&e.disabled!==null&&typeof e.disabled!="boolean"&&t.push("Nav action disabled must be a boolean"),e.extendedActions!==void 0&&e.extendedActions!==null&&(Array.isArray(e.extendedActions)?e.extendedActions.forEach((n,i)=>{if(typeof n!="object"||n===null){t.push(`Extended action at index ${i} must be an object`);return}const r=n;(!r.title||typeof r.title!="string")&&t.push(`Extended action at index ${i} is missing required "title" property`),r.subTitle!==void 0&&typeof r.subTitle!="string"&&t.push(`Extended action at index ${i} subTitle must be a string`),r.url!==void 0&&typeof r.url!="string"&&t.push(`Extended action at index ${i} url must be a string`),r.value!==void 0&&typeof r.value!="string"&&t.push(`Extended action at index ${i} value must be a string`),r.icon!==void 0&&typeof r.icon!="string"&&t.push(`Extended action at index ${i} icon must be a string`),r.disabled!==void 0&&typeof r.disabled!="boolean"&&t.push(`Extended action at index ${i} disabled must be a boolean`)}):t.push("Nav action extendedActions must be an array")),{valid:t.length===0,errors:t}}const R=["danger","warning","info"];function ie(e){const t=[];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"||!R.includes(e.variant))&&t.push(`Invalid confirm variant "${e.variant}". Expected: ${R.join(" | ")}`),{valid:t.length===0,errors:t}}function c(e,t){console.error(`[EmbeddedSDK] Validation failed for ${e}:
2
+ `+t.map(n=>` • ${n}`).join(`
3
+ `))}function ne(){return{navigate(e,t){const n=J({path:e,...t});if(!n.valid){c(h.NAVIGATE,n.errors);return}o(h.NAVIGATE,{path:e,state:t==null?void 0:t.state,replace:t==null?void 0:t.replace})},redirect(e){const t=ee({url:e});if(!t.valid){c(h.REDIRECT,t.errors);return}o(h.REDIRECT,{url:e})},navTo(e,t){if(e.startsWith("http://")||e.startsWith("https://")){this.redirect(e);return}this.navigate(e,t)},resize(e){if(typeof e!="number"||e<0){c(g.RESIZE,["Height must be a non-negative number"]);return}o(g.RESIZE,{height:e})},autoResize(){const e=document.documentElement.scrollHeight;this.resize(e)},setTitle(e){if(typeof e!="string"||!e.trim()){c(h.SET_TITLE,["Title must be a non-empty string"]);return}o(h.SET_TITLE,{title:e})}}}function re(){const e=new Set;let t=null;return E(b.ACTION_CLICK,i=>{if(t)try{t()}catch(r){console.error("[EmbeddedSDK] Error in onClick callback:",r)}e.forEach(r=>{try{r(i.url,i.value)}catch(l){console.error("[EmbeddedSDK] Error in action click callback:",l)}})}),{setAction(i){var l;const r=te(i);if(!r.valid){c(b.SET_ACTION,r.errors);return}i.onClick?t=i.onClick:t=null,o(b.SET_ACTION,{title:i.title,onClick:i.onClick?!0:void 0,value:i.value,subTitle:i.subTitle,icon:i.icon,disabled:i.disabled,extendedActions:(l=i.extendedActions)==null?void 0:l.map(a=>({title:a.title,subTitle:a.subTitle,url:a.url,value:a.value,icon:a.icon,disabled:a.disabled}))})},clearAction(){t=null,o(b.SET_ACTION,{title:""})},onActionClick(i){return e.add(i),()=>{e.delete(i)}},primaryAction(i){this.setAction(i)},clearPrimaryAction(){this.clearAction()}}}function se(){return{show(e="full"){o(u.LOADING,{status:!1,mode:e})},hide(){o(u.LOADING,{status:!0,mode:"full"})}}}function ae(){const e=t=>{const n=Q(t);if(!n.valid){c(u.TOAST,n.errors);return}o(u.TOAST,{type:t.type,message:t.message,duration:t.duration})};return{show:e,success(t,n){e({type:"success",message:t,duration:n})},error(t,n){e({type:"error",message:t,duration:n})},warning(t,n){e({type:"warning",message:t,duration:n})},info(t,n){e({type:"info",message:t,duration:n})}}}function oe(){return{open(e,t){o(u.MODAL,{action:"open",id:e,content:t})},close(e){o(u.MODAL,{action:"close",id:e})}}}function le(){return async e=>{const t=ie(e);return t.valid?Y(u.CONFIRM,{title:e.title,message:e.message,confirmText:e.confirmText??"Confirm",cancelText:e.cancelText??"Cancel",variant:e.variant??"info"}):(c(u.CONFIRM,t.errors),Promise.reject(new Error(t.errors.join(", "))))}}function ue(){return{loading:se(),toast:ae(),modal:oe(),confirm:le()}}function ce(){return{create(e){const t=B(e);if(!t.valid){c(S.CREATE,t.errors);return}o(S.CREATE,{payload:e})}}}const I={debug:!1,initialized:!1},de={theme:"light",width:0,locale:"ar",currency:"SAR"},N={ready:!1,initializing:!1,layout:{...de}};class D{constructor(){this.config={...I},this.state={...N},this.themeCallbacks=new Set,this.initCallbacks=new Set,this.appReady=!1,this.auth=X(),this.page=ne(),this.nav=re(),this.ui=ue(),this.checkout=ce(),this.setupThemeListener(),this.setupResponseListeners()}getState(){return{ready:this.state.ready,initializing:this.state.initializing,layout:{...this.state.layout}}}getConfig(){return{...this.config}}isReady(){return this.state.ready}debugLog(...t){this.config.debug&&console.log(`[EmbeddedSDK v${y}]`,...t)}warn(...t){console.warn(`[EmbeddedSDK v${y}]`,...t)}setupThemeListener(){E(p.THEME_CHANGE,t=>{this.state.layout.theme=t.theme,this.debugLog("Theme changed:",t.theme),this.themeCallbacks.forEach(n=>{try{n(t.theme)}catch(i){console.error("[EmbeddedSDK] Error in theme callback:",i)}})})}setupResponseListeners(){E(u.CONFIRM_RESPONSE,t=>{this.debugLog("Received confirm response:",t),A(t.requestId,{confirmed:t.confirmed})}),E(u.MODAL_RESPONSE,t=>{this.debugLog("Received modal response:",t),A(t.requestId,t.result,t.error)})}onThemeChange(t){return this.themeCallbacks.add(t),()=>{this.themeCallbacks.delete(t)}}onInit(t){if(this.config.initialized)try{t(this.getState())}catch(n){console.error("[EmbeddedSDK] Error in init callback:",n)}return this.initCallbacks.add(t),()=>{this.initCallbacks.delete(t)}}log(t,n,i){o(x.LOG,{level:t,message:n,context:i})}ready(){if(this.appReady){this.debugLog("App already signaled as ready");return}if(!this.config.initialized){this.warn("Cannot signal ready before init() is called");return}this.appReady=!0,o(g.READY,{}),this.debugLog("Sent ready signal to host")}async init(t={}){var n,i,r,l;if(this.config.initialized)return this.debugLog("Already initialized, returning current layout"),{layout:{...this.state.layout}};if(this.state.initializing)return this.warn("Initialization already in progress"),this.waitForInit();H()||this.warn("Not running in an iframe. Some features may not work."),this.config={debug:t.debug??!1,initialized:!1},this.state.initializing=!0,this.debugLog("Initializing SDK...");try{o(g.INIT,{height:document.documentElement.scrollHeight}),this.debugLog("Sent iframe.ready message, waiting for context...");const a=await q(p.PROVIDE);this.debugLog("Received context from host:",a),this.state={ready:!0,initializing:!1,layout:{theme:((n=a.layout)==null?void 0:n.theme)??"light",width:((i=a.layout)==null?void 0:i.width)??0,locale:((r=a.layout)==null?void 0:r.locale)??"ar",currency:((l=a.layout)==null?void 0:l.currency)??"SAR"}},this.config.initialized=!0,this.debugLog("Initialization complete. Layout:",this.state.layout);const w=this.getState();return this.initCallbacks.forEach($=>{try{$(w)}catch(k){console.error("[EmbeddedSDK] Error in init callback:",k)}}),{layout:{...this.state.layout}}}catch(a){throw this.state.initializing=!1,this.state.ready=!1,a}}waitForInit(){return new Promise(t=>{const n=()=>{this.state.ready?t({layout:{...this.state.layout}}):setTimeout(n,100)};n()})}destroy(){this.debugLog("Destroying SDK instance"),this.config.initialized&&(o(g.DESTROY,{}),this.debugLog("Sent destroy event to host")),Z("SDK destroyed"),G(),this.themeCallbacks.clear(),this.initCallbacks.clear(),this.config={...I},this.state={...N},this.appReady=!1}}let m=null;function O(){return m||(m=new D),m}function fe(){m&&(m.destroy(),m=null)}const v=O(),he=y;typeof window<"u"&&(window.salla=window.salla||window.Salla||{},window.Salla=window.salla,window.salla.embedded||(window.salla.embedded=v),window.Salla.embedded||(window.Salla.embedded=v));exports.EmbeddedApp=D;exports.embedded=v;exports.getEmbeddedApp=O;exports.resetEmbeddedApp=fe;exports.version=he;
4
4
  //# sourceMappingURL=index.js.map