esaalat 0.2.0 → 0.2.1

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.
@@ -164,7 +164,7 @@
164
164
  .overlay, .dialog { animation: none; }
165
165
  .spinner { animation-duration: 0.01ms; }
166
166
  }
167
- `;function c(i,t){let e=document.createElement(i);return t&&(e.className=t),e}function _(){let i=document.createElementNS("http://www.w3.org/2000/svg","svg");i.setAttribute("viewBox","0 0 24 24"),i.setAttribute("fill","none"),i.setAttribute("stroke","currentColor"),i.setAttribute("stroke-width","1.8"),i.setAttribute("stroke-linecap","round"),i.setAttribute("aria-hidden","true");let t=document.createElementNS("http://www.w3.org/2000/svg","path");return t.setAttribute("d","M18 6 6 18M6 6l12 12"),i.append(t),i}function D(){let i=document.createElementNS("http://www.w3.org/2000/svg","svg");i.setAttribute("viewBox","0 0 24 24"),i.setAttribute("fill","none"),i.setAttribute("stroke","currentColor"),i.setAttribute("stroke-width","1.8"),i.setAttribute("stroke-linecap","round"),i.setAttribute("stroke-linejoin","round"),i.setAttribute("aria-hidden","true");let t=document.createElementNS("http://www.w3.org/2000/svg","path");return t.setAttribute("d","M12 9v4M12 17h.01M10.3 3.9 2.5 17.4A2 2 0 0 0 4.2 20h15.6a2 2 0 0 0 1.7-2.6L13.7 3.9a2 2 0 0 0-3.4 0Z"),i.append(t),i}var y=class{constructor(t){this.options=t;this.frame=null;this.previousOverflow="";this.previousFocus=null;this.destroyed=!1;this.onLoad=null;this.handleKeyDown=t=>{t.key==="Escape"&&(t.preventDefault(),this.onDismiss())};this.onDismiss=t.onDismiss,this.host=document.createElement("div"),this.host.setAttribute("data-esaalat-checkout",""),this.host.style.cssText=`all: initial; position: fixed; inset: 0; z-index: ${t.zIndex}; pointer-events: none;`,this.shadow=this.host.attachShadow({mode:"open"});let e=c("style");e.textContent=M,this.shadow.append(e),this.overlay=c("div","overlay"),this.overlay.addEventListener("mousedown",d=>{d.target===this.overlay&&this.onDismiss()}),this.dialog=c("div","dialog"),this.dialog.setAttribute("role","dialog"),this.dialog.setAttribute("aria-modal","true"),this.dialog.setAttribute("aria-label",t.title);let r=c("div","chrome"),o=c("span","mark");o.textContent="E",o.setAttribute("aria-hidden","true");let a=c("span","chrome-title");a.textContent=t.title,this.closeButton=c("button","close"),this.closeButton.type="button",this.closeButton.setAttribute("aria-label",t.labels.close),this.closeButton.append(_()),this.closeButton.addEventListener("click",()=>this.onDismiss()),r.append(o,a,this.closeButton),this.content=c("div","content"),this.showLoading(),this.dialog.append(r,this.content),this.overlay.append(this.dialog),this.shadow.append(this.overlay)}open(){if(!document.body)throw new Error("Esaalat checkout needs a document body.");this.previousOverflow=document.body.style.overflow,this.previousFocus=document.activeElement,document.body.style.overflow="hidden",document.body.append(this.host),document.addEventListener("keydown",this.handleKeyDown,!0),this.closeButton.focus({preventScroll:!0})}load(t){if(this.destroyed)return;this.dialog.classList.add("is-frame"),this.content.replaceChildren();let e=document.createElement("iframe");e.className="frame",e.src=t,e.title=this.options.title,e.setAttribute("allow","clipboard-write"),e.setAttribute("referrerpolicy","strict-origin-when-cross-origin"),e.setAttribute("loading","eager"),e.addEventListener("load",()=>{this.onLoad?.();try{e.focus({preventScroll:!0})}catch{}}),this.frame=e,this.content.append(e)}get contentWindow(){return this.frame?.contentWindow??null}showError(t){if(this.destroyed)return;this.content.replaceChildren();let e=c("div","panel"),r=c("span","error-icon");r.append(D());let o=c("h2","error-title");o.textContent=this.options.labels.errorTitle;let a=c("p","error-message");a.textContent=t;let d=c("button","error-close");d.type="button",d.textContent=this.options.labels.close,d.addEventListener("click",()=>this.onDismiss()),e.append(r,o,a,d),this.content.append(e),this.dialog.classList.remove("is-frame"),d.focus({preventScroll:!0})}showLoading(){this.content.replaceChildren();let t=c("div","panel"),e=c("span","spinner");e.setAttribute("aria-hidden","true");let r=c("p","loading");r.textContent=this.options.labels.loading,t.append(e,r),this.content.append(t)}destroy(){if(!this.destroyed){if(this.destroyed=!0,document.removeEventListener("keydown",this.handleKeyDown,!0),document.body.style.overflow=this.previousOverflow,this.host.remove(),this.previousFocus instanceof HTMLElement&&this.previousFocus.isConnected)try{this.previousFocus.focus({preventScroll:!0})}catch{}this.onLoad=null,this.frame=null}}};var B="esaalat-checkout";var U=`
167
+ `;function c(o,t){let e=document.createElement(o);return t&&(e.className=t),e}function _(){let o=document.createElementNS("http://www.w3.org/2000/svg","svg");o.setAttribute("viewBox","0 0 24 24"),o.setAttribute("fill","none"),o.setAttribute("stroke","currentColor"),o.setAttribute("stroke-width","1.8"),o.setAttribute("stroke-linecap","round"),o.setAttribute("aria-hidden","true");let t=document.createElementNS("http://www.w3.org/2000/svg","path");return t.setAttribute("d","M18 6 6 18M6 6l12 12"),o.append(t),o}function D(){let o=document.createElementNS("http://www.w3.org/2000/svg","svg");o.setAttribute("viewBox","0 0 24 24"),o.setAttribute("fill","none"),o.setAttribute("stroke","currentColor"),o.setAttribute("stroke-width","1.8"),o.setAttribute("stroke-linecap","round"),o.setAttribute("stroke-linejoin","round"),o.setAttribute("aria-hidden","true");let t=document.createElementNS("http://www.w3.org/2000/svg","path");return t.setAttribute("d","M12 9v4M12 17h.01M10.3 3.9 2.5 17.4A2 2 0 0 0 4.2 20h15.6a2 2 0 0 0 1.7-2.6L13.7 3.9a2 2 0 0 0-3.4 0Z"),o.append(t),o}var y=class{constructor(t){this.options=t;this.frame=null;this.previousOverflow="";this.previousFocus=null;this.destroyed=!1;this.onLoad=null;this.handleKeyDown=t=>{t.key==="Escape"&&(t.preventDefault(),this.onDismiss())};this.onDismiss=t.onDismiss,this.host=document.createElement("div"),this.host.setAttribute("data-esaalat-checkout",""),this.host.style.cssText=`all: initial; position: fixed; inset: 0; z-index: ${t.zIndex}; pointer-events: none;`,this.shadow=this.host.attachShadow({mode:"open"});let e=c("style");e.textContent=M,this.shadow.append(e),this.overlay=c("div","overlay"),this.overlay.addEventListener("mousedown",d=>{d.target===this.overlay&&this.onDismiss()}),this.dialog=c("div","dialog"),this.dialog.setAttribute("role","dialog"),this.dialog.setAttribute("aria-modal","true"),this.dialog.setAttribute("aria-label",t.title);let r=c("div","chrome"),i=c("span","mark");i.textContent="E",i.setAttribute("aria-hidden","true");let a=c("span","chrome-title");a.textContent=t.title,this.closeButton=c("button","close"),this.closeButton.type="button",this.closeButton.setAttribute("aria-label",t.labels.close),this.closeButton.append(_()),this.closeButton.addEventListener("click",()=>this.onDismiss()),r.append(i,a,this.closeButton),this.content=c("div","content"),this.showLoading(),this.dialog.append(r,this.content),this.overlay.append(this.dialog),this.shadow.append(this.overlay)}open(){if(!document.body)throw new Error("Esaalat checkout needs a document body.");this.previousOverflow=document.body.style.overflow,this.previousFocus=document.activeElement,document.body.style.overflow="hidden",document.body.append(this.host),document.addEventListener("keydown",this.handleKeyDown,!0),this.closeButton.focus({preventScroll:!0})}load(t){if(this.destroyed)return;this.dialog.classList.add("is-frame"),this.content.replaceChildren();let e=document.createElement("iframe");e.className="frame",e.src=t,e.title=this.options.title,e.setAttribute("allow","clipboard-write"),e.setAttribute("referrerpolicy","strict-origin-when-cross-origin"),e.setAttribute("loading","eager"),e.addEventListener("load",()=>{this.onLoad?.();try{e.focus({preventScroll:!0})}catch{}}),this.frame=e,this.content.append(e)}get contentWindow(){return this.frame?.contentWindow??null}showError(t){if(this.destroyed)return;this.content.replaceChildren();let e=c("div","panel"),r=c("span","error-icon");r.append(D());let i=c("h2","error-title");i.textContent=this.options.labels.errorTitle;let a=c("p","error-message");a.textContent=t;let d=c("button","error-close");d.type="button",d.textContent=this.options.labels.close,d.addEventListener("click",()=>this.onDismiss()),e.append(r,i,a,d),this.content.append(e),this.dialog.classList.remove("is-frame"),d.focus({preventScroll:!0})}showLoading(){this.content.replaceChildren();let t=c("div","panel"),e=c("span","spinner");e.setAttribute("aria-hidden","true");let r=c("p","loading");r.textContent=this.options.labels.loading,t.append(e,r),this.content.append(t)}destroy(){if(!this.destroyed){if(this.destroyed=!0,document.removeEventListener("keydown",this.handleKeyDown,!0),document.body.style.overflow=this.previousOverflow,this.host.remove(),this.previousFocus instanceof HTMLElement&&this.previousFocus.isConnected)try{this.previousFocus.focus({preventScroll:!0})}catch{}this.onLoad=null,this.frame=null}}};var B="esaalat-checkout";var U=`
168
168
  * { box-sizing: border-box; }
169
169
  html, body { height: 100%; }
170
170
  body {
@@ -219,4 +219,4 @@
219
219
  .error-close { border-color: #343028; color: #f6f2e8; }
220
220
  .error-close:hover { background: #2b2721; }
221
221
  }
222
- `;function k(i){return i.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function N(){let i=window.screen?.availWidth??480,t=window.screen?.availHeight??800,e=Math.min(480,Math.max(320,i-40)),r=Math.min(800,Math.max(480,t-40)),o=typeof window.screenX=="number"?window.screenX:0,a=typeof window.screenY=="number"?window.screenY:0,d=window.outerWidth||e,m=window.outerHeight||r,h=Math.max(0,Math.round(o+(d-e)/2)),p=Math.max(0,Math.round(a+(m-r)/2));return["popup=yes",`width=${e}`,`height=${r}`,`left=${h}`,`top=${p}`,"resizable=yes","scrollbars=yes"].join(",")}function P(i,t,e,r){return["<!doctype html>",`<html dir="${t}" lang="${e}">`,"<head>",'<meta charset="utf-8" />','<meta name="viewport" content="width=device-width, initial-scale=1" />','<meta name="robots" content="noindex" />',`<title>${k(i)}</title>`,`<style>${U}</style>`,"</head>",`<body>${r}</body>`,"</html>"].join("")}var C=class{constructor(t){this.pollId=null;this.navigated=!1;this.destroyed=!1;this.onLoad=null;let e=window.open("",B,N());if(!e)throw new Error("The browser blocked the checkout window.");this.win=e,this.onDismiss=t.onDismiss,this.title=t.title,this.labels=t.labels,this.dir=t.dir,this.lang=t.lang,this.pollId=window.setInterval(()=>this.checkClosed(),400);try{this.win.focus()}catch{}}get contentWindow(){return this.win}open(){try{this.win.focus()}catch{}}load(t){if(!this.destroyed){this.navigated=!0;try{this.win.location.replace(t)}catch{if(this.win.closed){this.dismiss();return}try{this.win.location.href=t}catch{}}this.onLoad?.()}}showError(t){if(!(this.destroyed||this.navigated)){this.renderError(P(this.title,this.dir,this.lang,`<div class="panel"><span class="error-icon" aria-hidden="true">!</span><h2 class="error-title">${k(this.labels.errorTitle)}</h2><p class="error-message">${k(t)}</p><button class="error-close" type="button">${k(this.labels.close)}</button></div>`));try{this.win.document.querySelector(".error-close")?.addEventListener("click",()=>this.onDismiss())}catch{}}}destroy(){if(!this.destroyed){this.destroyed=!0,this.stopPolling(),this.onLoad=null;try{this.win.close()}catch{}}}renderError(t){try{let e=this.win.document;e.open(),e.write(t),e.close()}catch{}}checkClosed(){if(this.destroyed){this.stopPolling();return}this.win.closed&&this.dismiss()}dismiss(){this.destroyed||(this.stopPolling(),this.onDismiss())}stopPolling(){this.pollId!==null&&(window.clearInterval(this.pollId),this.pollId=null)}};var W="https://api.esaalat.com/api/v1",H="https://pay.esaalat.com",z="0.1.0",K=2e4,V=300,F=100,j=1800,$=6e3,G=["VERIFIED","WRONG_AMOUNT","EXPIRED","CANCELLED","FAILED"],Y=["dismissed","destroyed","intent_cancelled","session_expired","session_not_found","network_error"];function T(i,t){let e=i.trim()||t,r;try{let o=typeof window<"u"?window.location?.href:void 0;r=new URL(e,o)}catch{throw new n(`Invalid URL: ${e}`,"configuration")}if(r.protocol!=="http:"&&r.protocol!=="https:")throw new n(`Unsupported URL protocol: ${r.protocol}`,"configuration");return r.toString().replace(/\/+$/,"")}function q(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,i=>{let t=Math.random()*16|0;return(i==="x"?t:t&3|8).toString(16)})}function x(i,t=""){return typeof i=="string"?i:t}function O(i){return typeof i=="string"?i:null}function X(i){if(!i||typeof i!="object")return null;let t=i;if(typeof t.detail=="string")return t.detail;if(Array.isArray(t.errors)){for(let e of t.errors)if(e&&typeof e=="object"){let r=e.detail;if(typeof r=="string")return r}}for(let e of Object.values(t)){if(typeof e=="string")return e;if(Array.isArray(e)&&typeof e[0]=="string")return e[0]}return null}function J(i){if(!i||typeof i!="object")return!1;let t=i;return typeof t.session_token=="string"&&typeof t.portal_url=="string"&&typeof t.amount=="string"&&typeof t.currency=="string"}function A(i,t){return{status:"CANCELLED",reason:t,sessionToken:i??"",intentCode:null,amount:"0.00",paidAmount:null,currency:"YER",externalOrderId:"",merchantName:""}}var g=class{constructor(t){this.active=null;this.view=null;this.portalOrigin=null;this.sessionToken=null;this.initTimer=null;this.verifiedTimer=null;this.errorTimer=null;this.handleMessage=t=>{if(!this.view||!this.portalOrigin||t.source!==this.view.contentWindow||t.origin!==this.portalOrigin)return;let e=t.data;if(!(!e||typeof e!="object")&&e.source==="esaalat-checkout"&&e.sessionToken===this.sessionToken){if(e.type==="ready"){this.clearInitTimer();return}if(e.type==="close"){this.dismiss();return}if(e.type==="result"){let r=this.parseResult(e.payload);r&&this.finish(r)}}};let e=typeof t?.publishableKey=="string"?t.publishableKey.trim():"";this.publishableKey=e,this.locale=t.locale==="en"||t.locale==="ar"?t.locale:"ar",this.apiBaseUrl=T(t.apiBaseUrl??"",W),this.portalBaseUrl=T(t.portalBaseUrl??"",H),this.zIndex=typeof t.zIndex=="number"&&Number.isFinite(t.zIndex)?t.zIndex:2147483e3,this.presentation=t.presentation==="modal"?"modal":"window";let r=t.fetch,o=typeof fetch=="function"?fetch.bind(globalThis):null;this.fetchImpl=r??o,this.defaultOnResult=t.onResult,this.defaultOnError=t.onError}get isOpen(){return this.view!==null}async open(t={}){if(this.active||this.view)throw new n("A checkout is already open. Close it before starting another.","configuration");if(!this.fetchImpl)throw new n("This browser does not support fetch. Use the SDK on a modern browser.","configuration");let e=t.locale==="en"||t.locale==="ar"?t.locale:this.locale,r=t.items??[],o=t.sessionToken?.trim()||null,a=t.amount!==void 0&&t.amount!==null&&String(t.amount).trim()!=="";if(!o&&!this.publishableKey)throw new n("A publishable key is required to create a session. Pass one, or open a server-created `sessionToken`.","configuration");if(!o&&!a&&r.length===0)throw new n("Provide an amount, items, or a server-created session token.","configuration");if(!o&&r.length>0){for(let l of r)if(!l.name||l.price===void 0||l.price===null)throw new n("Every item needs a name and a price.","configuration")}let d=e==="ar"?{close:"\u0625\u063A\u0644\u0627\u0642",loading:"\u062C\u0627\u0631\u064D \u062A\u062C\u0647\u064A\u0632 \u0627\u0644\u062F\u0641\u0639 \u0627\u0644\u0622\u0645\u0646\u2026",errorTitle:"\u062A\u0639\u0630\u0651\u0631 \u0628\u062F\u0621 \u0627\u0644\u062F\u0641\u0639"}:{close:"Close",loading:"Preparing secure checkout\u2026",errorTitle:"Couldn't start the checkout"},m=t.presentation==="window"||t.presentation==="modal"?t.presentation:this.presentation,h;try{h=this.createView(m,d,e),h.open()}catch(l){throw new n("The checkout could not be opened.","unavailable",{cause:l})}let p=new AbortController,s,u,b=new Promise((l,v)=>{s=l,u=v}),I=t.onResult??this.defaultOnResult,R=t.onError??this.defaultOnError,f={token:null,locale:e,controller:p,view:h,settled:!1,resolve:s,reject:u,onResult:I};this.active=f,this.view=h,this.sessionToken=null,this.portalOrigin=null,h.onLoad=()=>this.startInitRetry();let w;try{if(o)f.token=o,this.sessionToken=o,w=this.buildPortalUrl(o,t.portalUrl??"",e);else{let l=await this.createSession(t,e,p.signal);if(f.settled)return b;f.token=l.session_token,this.sessionToken=l.session_token,w=this.buildPortalUrl(l.session_token,l.portal_url,e)}this.portalOrigin=new URL(w).origin}catch(l){if(f.settled)return b;let v=l instanceof n?l:new n("Esaalat returned an invalid checkout URL.","session",{cause:l});f.settled=!0,this.active=null,this.removeMessageListener();try{R?.(v)}catch{}return f.reject(v),h.showError(v.message),this.errorTimer=window.setTimeout(()=>{this.view===h&&this.teardown()},$),b}return window.addEventListener("message",this.handleMessage),h.load(w),b}close(){if(this.active){this.dismiss();return}this.teardown()}destroy(){if(this.active&&!this.active.settled){this.finish(A(this.sessionToken,"destroyed"));return}this.teardown()}createView(t,e,r){let o=r==="ar"?"\u0625\u064A\u0635\u0627\u0644\u0627\u062A \u2014 \u062F\u0641\u0639 \u0622\u0645\u0646":"Esaalat \u2014 Secure checkout",a=()=>this.dismiss();if(t==="window")try{return new C({title:o,labels:e,dir:r==="ar"?"rtl":"ltr",lang:r,onDismiss:a})}catch{}return new y({zIndex:this.zIndex,title:o,labels:e,onDismiss:a})}buildPortalUrl(t,e,r){let o=e.trim()||`${this.portalBaseUrl}/checkout/${encodeURIComponent(t)}`,a=new URL(o);if(a.protocol!=="http:"&&a.protocol!=="https:")throw new Error("Unsupported portal protocol");return a.searchParams.set("lang",r),a.toString()}async createSession(t,e,r){if(!this.fetchImpl)throw new n("fetch is unavailable","configuration");let o={};t.amount!==void 0&&t.amount!==null&&(o.amount=String(t.amount)),t.items?.length&&(o.items=t.items.map(s=>({name:s.name,...s.description?{description:s.description}:{},price:String(s.price),quantity:s.quantity??1}))),t.currency&&(o.currency=t.currency),t.externalOrderId&&(o.external_order_id=t.externalOrderId),t.notes&&(o.notes=t.notes),t.wallet&&(o.wallet=t.wallet);let a=t.onBeforeCreateOrder;if(a){let s;try{s=await a(o)}catch(u){throw new n(u instanceof Error&&u.message?u.message:e==="ar"?"\u0623\u064F\u0644\u063A\u064A \u0627\u0644\u062F\u0641\u0639.":"The checkout was cancelled.","configuration",{cause:u})}s&&typeof s=="object"&&(o=s)}let d=new AbortController,m=!1,h=window.setTimeout(()=>{m=!0,d.abort()},K),p=()=>d.abort();r.addEventListener("abort",p);try{let s=await this.fetchImpl(`${this.apiBaseUrl}/checkout/sdk/sessions/`,{method:"POST",credentials:"omit",cache:"no-store",headers:{Accept:"application/json","Content-Type":"application/json","ESAALAT-PUBLISHABLE-KEY":this.publishableKey,"ESAALAT-IDEMPOTENCY-KEY":t.idempotencyKey?.trim()||q(),"ESAALAT-SDK-VERSION":z},body:JSON.stringify(o),signal:d.signal}),u=await s.json().catch(()=>null);if(!s.ok)throw new n(X(u)||(e==="ar"?"\u062A\u0639\u0630\u0651\u0631 \u0625\u0646\u0634\u0627\u0621 \u062C\u0644\u0633\u0629 \u0627\u0644\u062F\u0641\u0639.":"Couldn't create the checkout session."),"api",{status:s.status,details:u});if(!J(u))throw new n("Esaalat returned an invalid checkout session.","session",{details:u});try{t.onOrderCreated?.(u)}catch{}return u}catch(s){throw s instanceof n?s:m?new n(e==="ar"?"\u0627\u0646\u062A\u0647\u062A \u0645\u0647\u0644\u0629 \u0627\u0644\u0627\u062A\u0635\u0627\u0644 \u0628\u0625\u064A\u0635\u0627\u0644\u0627\u062A. \u062D\u0627\u0648\u0644 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649.":"The connection to Esaalat timed out. Please try again.","network",{cause:s}):s instanceof DOMException&&s.name==="AbortError"?s:new n(e==="ar"?"\u062A\u0639\u0630\u0651\u0631 \u0627\u0644\u0627\u062A\u0635\u0627\u0644 \u0628\u0625\u064A\u0635\u0627\u0644\u0627\u062A. \u062A\u062D\u0642\u0642 \u0645\u0646 \u0627\u062A\u0635\u0627\u0644\u0643 \u0648\u062D\u0627\u0648\u0644 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649.":"Couldn't reach Esaalat. Check your connection and try again.","network",{cause:s})}finally{window.clearTimeout(h),r.removeEventListener("abort",p)}}startInitRetry(){this.clearInitTimer();let t=0,e=()=>{!this.view||!this.portalOrigin||!this.sessionToken||(this.postInit(),t+=1,t<F?this.initTimer=window.setTimeout(e,V):this.initTimer=null)};e()}postInit(){let t=this.view?.contentWindow;if(!t||!this.portalOrigin||!this.sessionToken)return;let e={source:"esaalat-checkout-sdk",version:1,type:"init",sessionToken:this.sessionToken,parentOrigin:window.location.origin,locale:this.active?.locale??this.locale};try{t.postMessage(e,this.portalOrigin)}catch{}}clearInitTimer(){this.initTimer!==null&&(window.clearTimeout(this.initTimer),this.initTimer=null)}parseResult(t){if(!t||typeof t!="object")return null;let e=t;if(typeof e.status!="string"||!G.includes(e.status))return null;let r=typeof e.reason=="string"&&Y.includes(e.reason)?e.reason:void 0;return{status:e.status,...r?{reason:r}:{},sessionToken:this.sessionToken??"",intentCode:O(e.intentCode),amount:x(e.amount,"0.00"),paidAmount:O(e.paidAmount),currency:x(e.currency,"YER"),externalOrderId:x(e.externalOrderId),merchantName:x(e.merchantName)}}finish(t){let e=this.active;if(!(!e||e.settled)){e.settled=!0,this.active=null,this.clearInitTimer(),e.controller.abort();try{e.onResult?.(t)}catch{}if(e.resolve(t),t.reason==="dismissed"||t.reason==="destroyed"){this.teardown();return}t.status==="VERIFIED"&&(this.verifiedTimer=window.setTimeout(()=>this.teardown(),j))}}dismiss(){if(this.active&&!this.active.settled){this.finish(A(this.sessionToken,"dismissed"));return}this.teardown()}removeMessageListener(){window.removeEventListener("message",this.handleMessage)}clearTimers(){this.clearInitTimer(),this.verifiedTimer!==null&&(window.clearTimeout(this.verifiedTimer),this.verifiedTimer=null),this.errorTimer!==null&&(window.clearTimeout(this.errorTimer),this.errorTimer=null)}teardown(){this.clearTimers(),this.removeMessageListener(),this.view&&(this.view.destroy(),this.view=null),this.portalOrigin=null,this.sessionToken=null,this.active=null}};var L="esaalat-checkout-button",Q={ar:"\u0627\u062F\u0641\u0639 \u0627\u0644\u0622\u0646",en:"Pay now"},Z={VERIFIED:{handler:"onVerified",event:"esaalat-verified"},CANCELLED:{handler:"onCancelled",event:"esaalat-cancelled"},WRONG_AMOUNT:{handler:"onWrongAmount",event:"esaalat-wrong-amount"},EXPIRED:{handler:"onExpired",event:"esaalat-expired"},FAILED:{handler:"onFailed",event:"esaalat-failed"}},ee={verified:"esaalat-verified",cancelled:"esaalat-cancelled",wrongAmount:"esaalat-wrong-amount",expired:"esaalat-expired",failed:"esaalat-failed",error:"esaalat-error"},te=300;function re(i){return i instanceof Error?i:new n(String(i)||"The checkout failed.","unavailable")}var E=class extends HTMLElement{constructor(){super(...arguments);this.items=null;this.client=null;this.clientKey=null;this.button=null;this.busy=!1;this.watchTimer=null;this.slotLabel=null;this.handleClick=()=>{this.start()}}static get observedAttributes(){return["publishable-key","amount","currency","external-order-id","notes","wallet","locale","presentation","session-token","portal-url","label","disabled","items"]}connectedCallback(){this.render()}disconnectedCallback(){this.stopWatch()}attributeChangedCallback(e,r,o){if(r!==o){if(e==="publishable-key"){this.client=null,this.clientKey=null;return}if(e==="label"||e==="locale"){this.applyLabel();return}e==="disabled"&&this.syncBusy()}}async open(){await this.start()}async start(){if(this.busy||this.isCheckoutOpen())return;let e=(this.getAttribute("publishable-key")??"").trim();if(!e&&!this.attribute("session-token")){this.reportError(new n("A publishable key is required.","configuration"));return}this.setBusy(!0),this.watch();try{let r=this.readItems(),a=await this.ensureClient(e).open(this.openOptions(r));this.handleResult(a)}catch(r){this.reportError(re(r))}finally{this.setBusy(!1)}}ensureClient(e){return this.client&&this.clientKey===e?this.client:(this.clientKey=e,this.client=new g({publishableKey:e,locale:this.locale()}),this.client)}openOptions(e){return{amount:this.attribute("amount"),items:e??void 0,currency:this.attribute("currency"),externalOrderId:this.attribute("external-order-id"),notes:this.attribute("notes"),wallet:this.attribute("wallet"),sessionToken:this.attribute("session-token"),portalUrl:this.attribute("portal-url"),locale:this.locale(),presentation:this.presentation(),onBeforeCreateOrder:this.onBeforeCreateOrder,onOrderCreated:this.onOrderCreated}}handleResult(e){let r=Z[e.status];r&&(this.callSafely(this[r.handler],e),this.dispatchOutcome(r.event,e))}reportError(e){this.callSafely(this.onError,e),this.dispatchOutcome(ee.error,e)}dispatchOutcome(e,r){this.dispatchEvent(new CustomEvent(e,{detail:r,bubbles:!0,composed:!0}))}callSafely(e,r){if(e)try{e(r)}catch{}}readItems(){if(this.items&&this.items.length>0)return this.items;let e=this.attribute("items");if(!e)return null;try{let r=JSON.parse(e);if(!Array.isArray(r))throw new Error("not an array");return r}catch{throw new n("The items attribute must be a JSON array of order lines.","configuration")}}attribute(e){return(this.getAttribute(e)??"").trim()||void 0}locale(){return this.getAttribute("locale")==="en"?"en":"ar"}presentation(){return this.getAttribute("presentation")==="window"?"window":"modal"}isCheckoutOpen(){return this.client?.isOpen??!1}render(){if(!this.button){this.slotLabel===null&&(this.slotLabel=(this.textContent??"").trim());let e=this.ownerDocument.createElement("button");e.type="button",e.className="esaalat-checkout-button",e.addEventListener("click",this.handleClick),this.replaceChildren(e),this.button=e,this.applyStyles(e)}this.applyLabel(),this.syncBusy()}applyLabel(){if(!this.button)return;let e=this.attribute("label")??(this.slotLabel||void 0)??Q[this.locale()];this.button.textContent=e}applyStyles(e){e.style.appearance="none",e.style.border="1px solid var(--esaalat-button-border, transparent)",e.style.borderRadius="var(--esaalat-button-radius, 12px)",e.style.background="var(--esaalat-button-background, #1f2a24)",e.style.color="var(--esaalat-button-color, #ffffff)",e.style.font="inherit",e.style.fontSize="var(--esaalat-button-font-size, 15px)",e.style.fontWeight="600",e.style.lineHeight="1.2",e.style.padding="var(--esaalat-button-padding, 14px 22px)",e.style.cursor="pointer",e.style.transition="opacity 120ms ease-out"}setBusy(e){this.busy=e,this.syncBusy()}syncBusy(){if(!this.button)return;let e=this.busy||this.isCheckoutOpen(),r=e||this.hasAttribute("disabled");this.button.disabled=r,this.button.setAttribute("aria-busy",e?"true":"false"),this.button.style.opacity=this.hasAttribute("disabled")&&!e?"0.6":"1",this.button.style.cursor=r?"default":"pointer"}watch(){this.watchTimer!==null||typeof setInterval!="function"||(this.watchTimer=setInterval(()=>{!this.busy&&!this.isCheckoutOpen()&&this.stopWatch(),this.syncBusy()},te))}stopWatch(){this.watchTimer!==null&&(clearInterval(this.watchTimer),this.watchTimer=null)}};function S(){return typeof customElements>"u"||customElements.get(L)?!1:(customElements.define(L,E),!0)}window.EsaalatCheckout=g;window.EsaalatCheckoutError=n;S();})();
222
+ `;function k(o){return o.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function H(){let o=window.screen?.availWidth??480,t=window.screen?.availHeight??800,e=Math.min(480,Math.max(320,o-40)),r=Math.min(800,Math.max(480,t-40)),i=typeof window.screenX=="number"?window.screenX:0,a=typeof window.screenY=="number"?window.screenY:0,d=window.outerWidth||e,m=window.outerHeight||r,h=Math.max(0,Math.round(i+(d-e)/2)),p=Math.max(0,Math.round(a+(m-r)/2));return["popup=yes",`width=${e}`,`height=${r}`,`left=${h}`,`top=${p}`,"resizable=yes","scrollbars=yes"].join(",")}function N(o,t,e,r){return["<!doctype html>",`<html dir="${t}" lang="${e}">`,"<head>",'<meta charset="utf-8" />','<meta name="viewport" content="width=device-width, initial-scale=1" />','<meta name="robots" content="noindex" />',`<title>${k(o)}</title>`,`<style>${U}</style>`,"</head>",`<body>${r}</body>`,"</html>"].join("")}var C=class{constructor(t){this.pollId=null;this.navigated=!1;this.destroyed=!1;this.onLoad=null;let e=window.open("",B,H());if(!e)throw new Error("The browser blocked the checkout window.");this.win=e,this.onDismiss=t.onDismiss,this.title=t.title,this.labels=t.labels,this.dir=t.dir,this.lang=t.lang,this.pollId=window.setInterval(()=>this.checkClosed(),400);try{this.win.focus()}catch{}}get contentWindow(){return this.win}open(){try{this.win.focus()}catch{}}load(t){if(!this.destroyed){this.navigated=!0;try{this.win.location.replace(t)}catch{if(this.win.closed){this.dismiss();return}try{this.win.location.href=t}catch{}}this.onLoad?.()}}showError(t){if(!(this.destroyed||this.navigated)){this.renderError(N(this.title,this.dir,this.lang,`<div class="panel"><span class="error-icon" aria-hidden="true">!</span><h2 class="error-title">${k(this.labels.errorTitle)}</h2><p class="error-message">${k(t)}</p><button class="error-close" type="button">${k(this.labels.close)}</button></div>`));try{this.win.document.querySelector(".error-close")?.addEventListener("click",()=>this.onDismiss())}catch{}}}destroy(){if(!this.destroyed){this.destroyed=!0,this.stopPolling(),this.onLoad=null;try{this.win.close()}catch{}}}renderError(t){try{let e=this.win.document;e.open(),e.write(t),e.close()}catch{}}checkClosed(){if(this.destroyed){this.stopPolling();return}this.win.closed&&this.dismiss()}dismiss(){this.destroyed||(this.stopPolling(),this.onDismiss())}stopPolling(){this.pollId!==null&&(window.clearInterval(this.pollId),this.pollId=null)}};var P="https://api.esaalat.com/api/v1",W="https://pay.esaalat.com",z="0.1.0",K=2e4,V=300,F=100,j=1800,$=6e3,G=["VERIFIED","WRONG_AMOUNT","EXPIRED","CANCELLED","FAILED"],Y=["dismissed","destroyed","intent_cancelled","session_expired","session_not_found","network_error"];function T(o,t){let e=o.trim()||t,r;try{let i=typeof window<"u"?window.location?.href:void 0;r=new URL(e,i)}catch{throw new n(`Invalid URL: ${e}`,"configuration")}if(r.protocol!=="http:"&&r.protocol!=="https:")throw new n(`Unsupported URL protocol: ${r.protocol}`,"configuration");return r.toString().replace(/\/+$/,"")}function q(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,o=>{let t=Math.random()*16|0;return(o==="x"?t:t&3|8).toString(16)})}function x(o,t=""){return typeof o=="string"?o:t}function O(o){return typeof o=="string"?o:null}function X(o){if(!o||typeof o!="object")return null;let t=o;if(typeof t.detail=="string")return t.detail;if(Array.isArray(t.errors)){for(let e of t.errors)if(e&&typeof e=="object"){let r=e.detail;if(typeof r=="string")return r}}for(let e of Object.values(t)){if(typeof e=="string")return e;if(Array.isArray(e)&&typeof e[0]=="string")return e[0]}return null}function J(o){if(!o||typeof o!="object")return!1;let t=o;return typeof t.session_token=="string"&&typeof t.portal_url=="string"&&typeof t.amount=="string"&&typeof t.currency=="string"}function A(o,t){return{status:"CANCELLED",reason:t,sessionToken:o??"",intentCode:null,amount:"0.00",paidAmount:null,currency:"YER",externalOrderId:"",merchantName:""}}var g=class{constructor(t){this.active=null;this.view=null;this.portalOrigin=null;this.sessionToken=null;this.initTimer=null;this.verifiedTimer=null;this.errorTimer=null;this.handleMessage=t=>{if(!this.view||!this.portalOrigin||t.source!==this.view.contentWindow||t.origin!==this.portalOrigin)return;let e=t.data;if(!(!e||typeof e!="object")&&e.source==="esaalat-checkout"&&e.sessionToken===this.sessionToken){if(e.type==="ready"){this.clearInitTimer();return}if(e.type==="close"){this.dismiss();return}if(e.type==="result"){let r=this.parseResult(e.payload);r&&this.finish(r)}}};let e=typeof t?.publishableKey=="string"?t.publishableKey.trim():"";this.publishableKey=e,this.locale=t.locale==="en"||t.locale==="ar"?t.locale:"ar",this.apiBaseUrl=T(t.apiBaseUrl??"",P),this.portalBaseUrl=T(t.portalBaseUrl??"",W),this.zIndex=typeof t.zIndex=="number"&&Number.isFinite(t.zIndex)?t.zIndex:2147483e3,this.presentation=t.presentation==="modal"?"modal":"window";let r=t.fetch,i=typeof fetch=="function"?fetch.bind(globalThis):null;this.fetchImpl=r??i,this.defaultOnResult=t.onResult,this.defaultOnError=t.onError}get isOpen(){return this.view!==null}async open(t={}){if(this.active||this.view)throw new n("A checkout is already open. Close it before starting another.","configuration");if(!this.fetchImpl)throw new n("This browser does not support fetch. Use the SDK on a modern browser.","configuration");let e=t.locale==="en"||t.locale==="ar"?t.locale:this.locale,r=t.items??[],i=t.sessionToken?.trim()||null,a=t.amount!==void 0&&t.amount!==null&&String(t.amount).trim()!=="";if(!i&&!this.publishableKey)throw new n("A publishable key is required to create a session. Pass one, or open a server-created `sessionToken`.","configuration");if(!i&&!a&&r.length===0)throw new n("Provide an amount, items, or a server-created session token.","configuration");if(!i&&r.length>0){for(let l of r)if(!l.name||l.price===void 0||l.price===null)throw new n("Every item needs a name and a price.","configuration")}let d=e==="ar"?{close:"\u0625\u063A\u0644\u0627\u0642",loading:"\u062C\u0627\u0631\u064D \u062A\u062C\u0647\u064A\u0632 \u0627\u0644\u062F\u0641\u0639 \u0627\u0644\u0622\u0645\u0646\u2026",errorTitle:"\u062A\u0639\u0630\u0651\u0631 \u0628\u062F\u0621 \u0627\u0644\u062F\u0641\u0639"}:{close:"Close",loading:"Preparing secure checkout\u2026",errorTitle:"Couldn't start the checkout"},m=t.presentation==="window"||t.presentation==="modal"?t.presentation:this.presentation,h;try{h=this.createView(m,d,e),h.open()}catch(l){throw new n("The checkout could not be opened.","unavailable",{cause:l})}let p=new AbortController,s,u,b=new Promise((l,v)=>{s=l,u=v}),I=t.onResult??this.defaultOnResult,R=t.onError??this.defaultOnError,f={token:null,locale:e,controller:p,view:h,settled:!1,resolve:s,reject:u,onResult:I};this.active=f,this.view=h,this.sessionToken=null,this.portalOrigin=null,h.onLoad=()=>this.startInitRetry();let w;try{if(i)f.token=i,this.sessionToken=i,w=this.buildPortalUrl(i,t.portalUrl??"",e);else{let l=await this.createSession(t,e,p.signal);if(f.settled)return b;f.token=l.session_token,this.sessionToken=l.session_token,w=this.buildPortalUrl(l.session_token,l.portal_url,e)}this.portalOrigin=new URL(w).origin}catch(l){if(f.settled)return b;let v=l instanceof n?l:new n("Esaalat returned an invalid checkout URL.","session",{cause:l});f.settled=!0,this.active=null,this.removeMessageListener();try{R?.(v)}catch{}return f.reject(v),h.showError(v.message),this.errorTimer=window.setTimeout(()=>{this.view===h&&this.teardown()},$),b}return window.addEventListener("message",this.handleMessage),h.load(w),b}close(){if(this.active){this.dismiss();return}this.teardown()}destroy(){if(this.active&&!this.active.settled){this.finish(A(this.sessionToken,"destroyed"));return}this.teardown()}createView(t,e,r){let i=r==="ar"?"\u0625\u064A\u0635\u0627\u0644\u0627\u062A \u2014 \u062F\u0641\u0639 \u0622\u0645\u0646":"Esaalat \u2014 Secure checkout",a=()=>this.dismiss();if(t==="window")try{return new C({title:i,labels:e,dir:r==="ar"?"rtl":"ltr",lang:r,onDismiss:a})}catch{}return new y({zIndex:this.zIndex,title:i,labels:e,onDismiss:a})}buildPortalUrl(t,e,r){let i=e.trim()||`${this.portalBaseUrl}/checkout/${encodeURIComponent(t)}`,a=new URL(i);if(a.protocol!=="http:"&&a.protocol!=="https:")throw new Error("Unsupported portal protocol");return a.searchParams.set("lang",r),a.toString()}async createSession(t,e,r){if(!this.fetchImpl)throw new n("fetch is unavailable","configuration");let i={};t.amount!==void 0&&t.amount!==null&&(i.amount=String(t.amount)),t.items?.length&&(i.items=t.items.map(s=>({name:s.name,...s.description?{description:s.description}:{},price:String(s.price),quantity:s.quantity??1}))),t.currency&&(i.currency=t.currency),t.externalOrderId&&(i.external_order_id=t.externalOrderId),t.notes&&(i.notes=t.notes),t.wallet&&(i.wallet=t.wallet);let a=t.onBeforeCreateOrder;if(a){let s;try{s=await a(i)}catch(u){throw new n(u instanceof Error&&u.message?u.message:e==="ar"?"\u0623\u064F\u0644\u063A\u064A \u0627\u0644\u062F\u0641\u0639.":"The checkout was cancelled.","configuration",{cause:u})}s&&typeof s=="object"&&(i=s)}let d=new AbortController,m=!1,h=window.setTimeout(()=>{m=!0,d.abort()},K),p=()=>d.abort();r.addEventListener("abort",p);try{let s=await this.fetchImpl(`${this.apiBaseUrl}/checkout/sdk/sessions/`,{method:"POST",credentials:"omit",cache:"no-store",headers:{Accept:"application/json","Content-Type":"application/json","ESAALAT-PUBLISHABLE-KEY":this.publishableKey,"ESAALAT-IDEMPOTENCY-KEY":t.idempotencyKey?.trim()||q(),"ESAALAT-SDK-VERSION":z},body:JSON.stringify(i),signal:d.signal}),u=await s.json().catch(()=>null);if(!s.ok)throw new n(X(u)||(e==="ar"?"\u062A\u0639\u0630\u0651\u0631 \u0625\u0646\u0634\u0627\u0621 \u062C\u0644\u0633\u0629 \u0627\u0644\u062F\u0641\u0639.":"Couldn't create the checkout session."),"api",{status:s.status,details:u});if(!J(u))throw new n("Esaalat returned an invalid checkout session.","session",{details:u});try{t.onOrderCreated?.(u)}catch{}return u}catch(s){throw s instanceof n?s:m?new n(e==="ar"?"\u0627\u0646\u062A\u0647\u062A \u0645\u0647\u0644\u0629 \u0627\u0644\u0627\u062A\u0635\u0627\u0644 \u0628\u0625\u064A\u0635\u0627\u0644\u0627\u062A. \u062D\u0627\u0648\u0644 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649.":"The connection to Esaalat timed out. Please try again.","network",{cause:s}):s instanceof DOMException&&s.name==="AbortError"?s:new n(e==="ar"?"\u062A\u0639\u0630\u0651\u0631 \u0627\u0644\u0627\u062A\u0635\u0627\u0644 \u0628\u0625\u064A\u0635\u0627\u0644\u0627\u062A. \u062A\u062D\u0642\u0642 \u0645\u0646 \u0627\u062A\u0635\u0627\u0644\u0643 \u0648\u062D\u0627\u0648\u0644 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649.":"Couldn't reach Esaalat. Check your connection and try again.","network",{cause:s})}finally{window.clearTimeout(h),r.removeEventListener("abort",p)}}startInitRetry(){this.clearInitTimer();let t=0,e=()=>{!this.view||!this.portalOrigin||!this.sessionToken||(this.postInit(),t+=1,t<F?this.initTimer=window.setTimeout(e,V):this.initTimer=null)};e()}postInit(){let t=this.view?.contentWindow;if(!t||!this.portalOrigin||!this.sessionToken)return;let e={source:"esaalat-checkout-sdk",version:1,type:"init",sessionToken:this.sessionToken,parentOrigin:window.location.origin,locale:this.active?.locale??this.locale};try{t.postMessage(e,this.portalOrigin)}catch{}}clearInitTimer(){this.initTimer!==null&&(window.clearTimeout(this.initTimer),this.initTimer=null)}parseResult(t){if(!t||typeof t!="object")return null;let e=t;if(typeof e.status!="string"||!G.includes(e.status))return null;let r=typeof e.reason=="string"&&Y.includes(e.reason)?e.reason:void 0;return{status:e.status,...r?{reason:r}:{},sessionToken:this.sessionToken??"",intentCode:O(e.intentCode),amount:x(e.amount,"0.00"),paidAmount:O(e.paidAmount),currency:x(e.currency,"YER"),externalOrderId:x(e.externalOrderId),merchantName:x(e.merchantName)}}finish(t){let e=this.active;if(!(!e||e.settled)){e.settled=!0,this.active=null,this.clearInitTimer(),e.controller.abort();try{e.onResult?.(t)}catch{}if(e.resolve(t),t.reason==="dismissed"||t.reason==="destroyed"){this.teardown();return}t.status==="VERIFIED"&&(this.verifiedTimer=window.setTimeout(()=>this.teardown(),j))}}dismiss(){if(this.active&&!this.active.settled){this.finish(A(this.sessionToken,"dismissed"));return}this.teardown()}removeMessageListener(){window.removeEventListener("message",this.handleMessage)}clearTimers(){this.clearInitTimer(),this.verifiedTimer!==null&&(window.clearTimeout(this.verifiedTimer),this.verifiedTimer=null),this.errorTimer!==null&&(window.clearTimeout(this.errorTimer),this.errorTimer=null)}teardown(){this.clearTimers(),this.removeMessageListener(),this.view&&(this.view.destroy(),this.view=null),this.portalOrigin=null,this.sessionToken=null,this.active=null}};var L="esaalat-checkout-button",Q={ar:"\u0627\u062F\u0641\u0639 \u0627\u0644\u0622\u0646",en:"Pay now"},Z={VERIFIED:{handler:"onVerified",event:"esaalat-verified"},CANCELLED:{handler:"onCancelled",event:"esaalat-cancelled"},WRONG_AMOUNT:{handler:"onWrongAmount",event:"esaalat-wrong-amount"},EXPIRED:{handler:"onExpired",event:"esaalat-expired"},FAILED:{handler:"onFailed",event:"esaalat-failed"}},ee={verified:"esaalat-verified",cancelled:"esaalat-cancelled",wrongAmount:"esaalat-wrong-amount",expired:"esaalat-expired",failed:"esaalat-failed",error:"esaalat-error"},te=300;function re(o){return o instanceof Error?o:new n(String(o)||"The checkout failed.","unavailable")}var oe=typeof HTMLElement>"u"?class{}:HTMLElement,E=class extends oe{constructor(){super(...arguments);this.items=null;this.client=null;this.clientKey=null;this.button=null;this.busy=!1;this.watchTimer=null;this.slotLabel=null;this.handleClick=()=>{this.start()}}static get observedAttributes(){return["publishable-key","amount","currency","external-order-id","notes","wallet","locale","presentation","session-token","portal-url","label","disabled","items"]}connectedCallback(){this.render()}disconnectedCallback(){this.stopWatch()}attributeChangedCallback(e,r,i){if(r!==i){if(e==="publishable-key"){this.client=null,this.clientKey=null;return}if(e==="label"||e==="locale"){this.applyLabel();return}e==="disabled"&&this.syncBusy()}}async open(){await this.start()}async start(){if(this.busy||this.isCheckoutOpen())return;let e=(this.getAttribute("publishable-key")??"").trim();if(!e&&!this.attribute("session-token")){this.reportError(new n("A publishable key is required.","configuration"));return}this.setBusy(!0),this.watch();try{let r=this.readItems(),a=await this.ensureClient(e).open(this.openOptions(r));this.handleResult(a)}catch(r){this.reportError(re(r))}finally{this.setBusy(!1)}}ensureClient(e){return this.client&&this.clientKey===e?this.client:(this.clientKey=e,this.client=new g({publishableKey:e,locale:this.locale()}),this.client)}openOptions(e){return{amount:this.attribute("amount"),items:e??void 0,currency:this.attribute("currency"),externalOrderId:this.attribute("external-order-id"),notes:this.attribute("notes"),wallet:this.attribute("wallet"),sessionToken:this.attribute("session-token"),portalUrl:this.attribute("portal-url"),locale:this.locale(),presentation:this.presentation(),onBeforeCreateOrder:this.onBeforeCreateOrder,onOrderCreated:this.onOrderCreated}}handleResult(e){let r=Z[e.status];r&&(this.callSafely(this[r.handler],e),this.dispatchOutcome(r.event,e))}reportError(e){this.callSafely(this.onError,e),this.dispatchOutcome(ee.error,e)}dispatchOutcome(e,r){this.dispatchEvent(new CustomEvent(e,{detail:r,bubbles:!0,composed:!0}))}callSafely(e,r){if(e)try{e(r)}catch{}}readItems(){if(this.items&&this.items.length>0)return this.items;let e=this.attribute("items");if(!e)return null;try{let r=JSON.parse(e);if(!Array.isArray(r))throw new Error("not an array");return r}catch{throw new n("The items attribute must be a JSON array of order lines.","configuration")}}attribute(e){return(this.getAttribute(e)??"").trim()||void 0}locale(){return this.getAttribute("locale")==="en"?"en":"ar"}presentation(){return this.getAttribute("presentation")==="window"?"window":"modal"}isCheckoutOpen(){return this.client?.isOpen??!1}render(){if(!this.button){this.slotLabel===null&&(this.slotLabel=(this.textContent??"").trim());let e=this.ownerDocument.createElement("button");e.type="button",e.className="esaalat-checkout-button",e.addEventListener("click",this.handleClick),this.replaceChildren(e),this.button=e,this.applyStyles(e)}this.applyLabel(),this.syncBusy()}applyLabel(){if(!this.button)return;let e=this.attribute("label")??(this.slotLabel||void 0)??Q[this.locale()];this.button.textContent=e}applyStyles(e){e.style.appearance="none",e.style.border="1px solid var(--esaalat-button-border, transparent)",e.style.borderRadius="var(--esaalat-button-radius, 12px)",e.style.background="var(--esaalat-button-background, #1f2a24)",e.style.color="var(--esaalat-button-color, #ffffff)",e.style.font="inherit",e.style.fontSize="var(--esaalat-button-font-size, 15px)",e.style.fontWeight="600",e.style.lineHeight="1.2",e.style.padding="var(--esaalat-button-padding, 14px 22px)",e.style.cursor="pointer",e.style.transition="opacity 120ms ease-out"}setBusy(e){this.busy=e,this.syncBusy()}syncBusy(){if(!this.button)return;let e=this.busy||this.isCheckoutOpen(),r=e||this.hasAttribute("disabled");this.button.disabled=r,this.button.setAttribute("aria-busy",e?"true":"false"),this.button.style.opacity=this.hasAttribute("disabled")&&!e?"0.6":"1",this.button.style.cursor=r?"default":"pointer"}watch(){this.watchTimer!==null||typeof setInterval!="function"||(this.watchTimer=setInterval(()=>{!this.busy&&!this.isCheckoutOpen()&&this.stopWatch(),this.syncBusy()},te))}stopWatch(){this.watchTimer!==null&&(clearInterval(this.watchTimer),this.watchTimer=null)}};function S(){return typeof customElements>"u"||customElements.get(L)?!1:(customElements.define(L,E),!0)}window.EsaalatCheckout=g;window.EsaalatCheckoutError=n;S();})();
package/dist/index.cjs CHANGED
@@ -1154,7 +1154,9 @@ function asError(error) {
1154
1154
  if (error instanceof Error) return error;
1155
1155
  return new EsaalatCheckoutError(String(error) || "The checkout failed.", "unavailable");
1156
1156
  }
1157
- var EsaalatCheckoutButtonElement = class extends HTMLElement {
1157
+ var HTMLElementBase = typeof HTMLElement === "undefined" ? class {
1158
+ } : HTMLElement;
1159
+ var EsaalatCheckoutButtonElement = class extends HTMLElementBase {
1158
1160
  constructor() {
1159
1161
  super(...arguments);
1160
1162
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/modal.ts","../src/window.ts","../src/client.ts","../src/element.ts"],"sourcesContent":["export { EsaalatCheckout } from \"./client\";\nexport {\n ESAALAT_CHECKOUT_BUTTON_TAG,\n ESAALAT_CHECKOUT_EVENTS,\n EsaalatCheckoutButtonElement,\n registerEsaalatCheckoutButton,\n} from \"./element\";\nexport { EsaalatCheckoutError } from \"./errors\";\nexport type { CheckoutErrorCode } from \"./errors\";\nexport type {\n CheckoutBeforeCreateOrderHandler,\n CheckoutCreatePayload,\n CheckoutItem,\n CheckoutIntent,\n CheckoutLocale,\n CheckoutOpenOptions,\n CheckoutPresentation,\n CheckoutProvider,\n CheckoutResult,\n CheckoutResultReason,\n CheckoutResultStatus,\n CheckoutSession,\n CheckoutWallet,\n EsaalatCheckoutOptions,\n ExpectedReferenceType,\n} from \"./types\";\n\nexport { EsaalatCheckout as default } from \"./client\";\n","export type CheckoutErrorCode =\n | \"configuration\"\n | \"network\"\n | \"api\"\n | \"session\"\n | \"unavailable\"\n | \"aborted\";\n\nexport class EsaalatCheckoutError extends Error {\n readonly code: CheckoutErrorCode;\n readonly status?: number;\n readonly details?: unknown;\n\n constructor(\n message: string,\n code: CheckoutErrorCode,\n options: { status?: number; details?: unknown; cause?: unknown } = {}\n ) {\n super(message);\n this.name = \"EsaalatCheckoutError\";\n this.code = code;\n this.status = options.status;\n this.details = options.details;\n if (options.cause !== undefined) {\n // `cause` is ES2022; assigning it keeps the package ES2020-compatible.\n (this as Error & { cause?: unknown }).cause = options.cause;\n }\n }\n}\n","import type { CheckoutView } from \"./view\";\n\nexport interface CheckoutModalLabels {\n close: string;\n loading: string;\n errorTitle: string;\n}\n\ninterface CheckoutModalOptions {\n zIndex: number;\n title: string;\n labels: CheckoutModalLabels;\n onDismiss: () => void;\n}\n\nconst MODAL_CSS = `\n :host { all: initial; }\n *, *::before, *::after { box-sizing: border-box; }\n .overlay {\n position: fixed;\n inset: 0;\n z-index: 0;\n display: grid;\n place-items: center;\n padding: 12px;\n background: rgba(12, 11, 8, 0.58);\n -webkit-backdrop-filter: blur(7px);\n backdrop-filter: blur(7px);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n color: #0b0b0b;\n pointer-events: auto;\n animation: fade 180ms ease-out;\n }\n .dialog {\n position: relative;\n width: min(460px, calc(100vw - 24px));\n height: min(720px, calc(100dvh - 24px));\n overflow: hidden;\n border-radius: 22px;\n background: #fffefa;\n border: 1px solid rgba(255, 255, 255, 0.5);\n box-shadow: 0 36px 100px rgba(0, 0, 0, 0.4), 0 6px 24px rgba(0, 0, 0, 0.2);\n animation: rise 220ms cubic-bezier(0.2, 0.8, 0.2, 1);\n }\n .dialog.is-frame { background: #f3f0e8; }\n .chrome {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 14px 16px;\n border-bottom: 1px solid #e7e2d7;\n background: #fffefa;\n }\n .dialog.is-frame .chrome { display: none; }\n .mark {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n display: grid;\n place-items: center;\n background: #0b0b0b;\n color: #fff;\n font-size: 14px;\n font-weight: 800;\n flex-shrink: 0;\n }\n .chrome-title {\n font-size: 13px;\n font-weight: 700;\n line-height: 1.3;\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .close {\n width: 32px;\n height: 32px;\n display: grid;\n place-items: center;\n border: 0;\n border-radius: 9px;\n background: transparent;\n color: #716f67;\n cursor: pointer;\n flex-shrink: 0;\n }\n .close:hover { background: #f3f0e8; color: #0b0b0b; }\n .close:focus-visible { outline: 2px solid #0b0b0b; outline-offset: 2px; }\n .close svg { width: 18px; height: 18px; }\n .content {\n position: absolute;\n inset: 57px 0 0;\n overflow: hidden;\n }\n .dialog.is-frame .content { inset: 0; }\n .frame {\n display: block;\n width: 100%;\n height: 100%;\n border: 0;\n background: #f3f0e8;\n }\n .panel {\n height: 100%;\n display: grid;\n place-content: center;\n justify-items: center;\n gap: 12px;\n padding: 32px;\n text-align: center;\n }\n .spinner {\n width: 34px;\n height: 34px;\n border-radius: 50%;\n border: 2px solid #e7e2d7;\n border-top-color: #0b0b0b;\n animation: spin 900ms linear infinite;\n }\n .loading { font-size: 13px; color: #716f67; }\n .error-icon {\n width: 54px;\n height: 54px;\n border-radius: 50%;\n display: grid;\n place-items: center;\n background: #fef1ef;\n border: 1px solid #f5cfca;\n color: #b42318;\n }\n .error-icon svg { width: 25px; height: 25px; }\n .error-title { margin: 0; font-size: 17px; line-height: 1.4; }\n .error-message { margin: 0; font-size: 13px; line-height: 1.7; color: #716f67; max-width: 34ch; }\n .error-close {\n margin-top: 6px;\n min-height: 42px;\n padding: 9px 22px;\n border: 1px solid #e7e2d7;\n border-radius: 11px;\n background: transparent;\n color: #0b0b0b;\n font: inherit;\n font-size: 13px;\n font-weight: 700;\n cursor: pointer;\n }\n .error-close:hover { background: #f3f0e8; }\n .error-close:focus-visible { outline: 2px solid #0b0b0b; outline-offset: 2px; }\n @keyframes spin { to { transform: rotate(360deg); } }\n @keyframes fade { from { opacity: 0; } }\n @keyframes rise { from { opacity: 0; transform: translateY(10px) scale(0.985); } }\n @media (max-width: 520px) {\n .overlay { padding: 0; }\n .dialog {\n width: 100vw;\n height: 100dvh;\n max-height: none;\n border-radius: 0;\n border: 0;\n }\n .chrome { padding-top: calc(14px + env(safe-area-inset-top)); }\n }\n @media (prefers-color-scheme: dark) {\n .overlay { background: rgba(0, 0, 0, 0.7); }\n .dialog, .chrome { background: #1d1b17; border-color: #343028; color: #f6f2e8; }\n .dialog.is-frame, .frame { background: #141310; }\n .chrome-title { color: #f6f2e8; }\n .close { color: #aaa59a; }\n .close:hover { background: #2b2721; color: #f6f2e8; }\n .spinner { border-color: #343028; border-top-color: #f6f2e8; }\n .loading, .error-message { color: #aaa59a; }\n .error-icon { background: #2b1b19; border-color: #4b2c28; color: #f18d83; }\n .error-close { border-color: #343028; color: #f6f2e8; }\n .error-close:hover { background: #2b2721; }\n }\n @media (prefers-reduced-motion: reduce) {\n .overlay, .dialog { animation: none; }\n .spinner { animation-duration: 0.01ms; }\n }\n`;\n\nfunction element<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n className?: string\n): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n if (className) node.className = className;\n return node;\n}\n\nfunction closeSvg(): SVGSVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"1.8\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", \"M18 6 6 18M6 6l12 12\");\n svg.append(path);\n return svg;\n}\n\nfunction alertSvg(): SVGSVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"1.8\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", \"M12 9v4M12 17h.01M10.3 3.9 2.5 17.4A2 2 0 0 0 4.2 20h15.6a2 2 0 0 0 1.7-2.6L13.7 3.9a2 2 0 0 0-3.4 0Z\");\n svg.append(path);\n return svg;\n}\n\n/**\n * The modal lives in a shadow root so a merchant's global CSS cannot leak into\n * the checkout (or the other way around). The iframe is the only content once\n * the session is ready; the portal owns its own close button.\n */\nexport class CheckoutModal implements CheckoutView {\n private readonly host: HTMLDivElement;\n private readonly shadow: ShadowRoot;\n private readonly overlay: HTMLDivElement;\n private readonly dialog: HTMLDivElement;\n private readonly closeButton: HTMLButtonElement;\n private readonly content: HTMLDivElement;\n private frame: HTMLIFrameElement | null = null;\n private previousOverflow = \"\";\n private previousFocus: Element | null = null;\n private destroyed = false;\n\n onLoad: (() => void) | null = null;\n private readonly onDismiss: () => void;\n\n constructor(private readonly options: CheckoutModalOptions) {\n this.onDismiss = options.onDismiss;\n\n this.host = document.createElement(\"div\");\n this.host.setAttribute(\"data-esaalat-checkout\", \"\");\n this.host.style.cssText = `all: initial; position: fixed; inset: 0; z-index: ${options.zIndex}; pointer-events: none;`;\n\n this.shadow = this.host.attachShadow({ mode: \"open\" });\n const style = element(\"style\");\n style.textContent = MODAL_CSS;\n this.shadow.append(style);\n\n this.overlay = element(\"div\", \"overlay\");\n this.overlay.addEventListener(\"mousedown\", (event) => {\n if (event.target === this.overlay) this.onDismiss();\n });\n\n this.dialog = element(\"div\", \"dialog\");\n this.dialog.setAttribute(\"role\", \"dialog\");\n this.dialog.setAttribute(\"aria-modal\", \"true\");\n this.dialog.setAttribute(\"aria-label\", options.title);\n\n const chrome = element(\"div\", \"chrome\");\n const mark = element(\"span\", \"mark\");\n mark.textContent = \"E\";\n mark.setAttribute(\"aria-hidden\", \"true\");\n const title = element(\"span\", \"chrome-title\");\n title.textContent = options.title;\n\n this.closeButton = element(\"button\", \"close\");\n this.closeButton.type = \"button\";\n this.closeButton.setAttribute(\"aria-label\", options.labels.close);\n this.closeButton.append(closeSvg());\n this.closeButton.addEventListener(\"click\", () => this.onDismiss());\n\n chrome.append(mark, title, this.closeButton);\n\n this.content = element(\"div\", \"content\");\n this.showLoading();\n\n this.dialog.append(chrome, this.content);\n this.overlay.append(this.dialog);\n this.shadow.append(this.overlay);\n }\n\n open(): void {\n if (!document.body) {\n throw new Error(\"Esaalat checkout needs a document body.\");\n }\n this.previousOverflow = document.body.style.overflow;\n this.previousFocus = document.activeElement;\n document.body.style.overflow = \"hidden\";\n document.body.append(this.host);\n document.addEventListener(\"keydown\", this.handleKeyDown, true);\n this.closeButton.focus({ preventScroll: true });\n }\n\n load(url: string): void {\n if (this.destroyed) return;\n this.dialog.classList.add(\"is-frame\");\n this.content.replaceChildren();\n\n const frame = document.createElement(\"iframe\");\n frame.className = \"frame\";\n frame.src = url;\n frame.title = this.options.title;\n frame.setAttribute(\"allow\", \"clipboard-write\");\n frame.setAttribute(\"referrerpolicy\", \"strict-origin-when-cross-origin\");\n frame.setAttribute(\"loading\", \"eager\");\n frame.addEventListener(\"load\", () => {\n this.onLoad?.();\n try {\n frame.focus({ preventScroll: true });\n } catch {\n // focus is best-effort in embedded browsers\n }\n });\n\n this.frame = frame;\n this.content.append(frame);\n }\n\n get contentWindow(): Window | null {\n return this.frame?.contentWindow ?? null;\n }\n\n showError(message: string): void {\n if (this.destroyed) return;\n this.content.replaceChildren();\n\n const panel = element(\"div\", \"panel\");\n const icon = element(\"span\", \"error-icon\");\n icon.append(alertSvg());\n const title = element(\"h2\", \"error-title\");\n title.textContent = this.options.labels.errorTitle;\n const text = element(\"p\", \"error-message\");\n text.textContent = message;\n const close = element(\"button\", \"error-close\");\n close.type = \"button\";\n close.textContent = this.options.labels.close;\n close.addEventListener(\"click\", () => this.onDismiss());\n\n panel.append(icon, title, text, close);\n this.content.append(panel);\n this.dialog.classList.remove(\"is-frame\");\n close.focus({ preventScroll: true });\n }\n\n private showLoading(): void {\n this.content.replaceChildren();\n const panel = element(\"div\", \"panel\");\n const spinner = element(\"span\", \"spinner\");\n spinner.setAttribute(\"aria-hidden\", \"true\");\n const label = element(\"p\", \"loading\");\n label.textContent = this.options.labels.loading;\n panel.append(spinner, label);\n this.content.append(panel);\n }\n\n private handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n this.onDismiss();\n }\n };\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n document.removeEventListener(\"keydown\", this.handleKeyDown, true);\n document.body.style.overflow = this.previousOverflow;\n this.host.remove();\n if (this.previousFocus instanceof HTMLElement && this.previousFocus.isConnected) {\n try {\n this.previousFocus.focus({ preventScroll: true });\n } catch {\n // ignore\n }\n }\n this.onLoad = null;\n this.frame = null;\n }\n}\n","import type { CheckoutView } from \"./view\";\n\nexport interface CheckoutWindowOptions {\n title: string;\n labels: {\n loading: string;\n errorTitle: string;\n close: string;\n };\n dir: \"rtl\" | \"ltr\";\n lang: string;\n onDismiss: () => void;\n}\n\nconst WINDOW_NAME = \"esaalat-checkout\";\nconst WINDOW_WIDTH = 480;\nconst WINDOW_HEIGHT = 800;\nconst CLOSE_POLL_MS = 400;\n\nconst DOC_CSS = `\n * { box-sizing: border-box; }\n html, body { height: 100%; }\n body {\n margin: 0;\n display: grid;\n place-items: center;\n padding: 24px;\n background: #f3f0e8;\n color: #0b0b0b;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n }\n .panel {\n display: grid;\n justify-items: center;\n gap: 14px;\n max-width: 34ch;\n text-align: center;\n }\n .error-icon {\n width: 54px;\n height: 54px;\n border-radius: 50%;\n display: grid;\n place-items: center;\n background: #fef1ef;\n border: 1px solid #f5cfca;\n color: #b42318;\n font-size: 24px;\n font-weight: 800;\n }\n .error-title { margin: 0; font-size: 17px; line-height: 1.4; }\n .error-message { margin: 0; font-size: 13px; line-height: 1.7; color: #716f67; }\n .error-close {\n margin-top: 4px;\n min-height: 42px;\n padding: 9px 22px;\n border: 1px solid #ded7c8;\n border-radius: 11px;\n background: transparent;\n color: #0b0b0b;\n font: inherit;\n font-size: 13px;\n font-weight: 700;\n cursor: pointer;\n }\n .error-close:hover { background: #e9e4d8; }\n @media (prefers-color-scheme: dark) {\n body { background: #141310; color: #f6f2e8; }\n .error-message { color: #aaa59a; }\n .error-icon { background: #2b1b19; border-color: #4b2c28; color: #f18d83; }\n .error-close { border-color: #343028; color: #f6f2e8; }\n .error-close:hover { background: #2b2721; }\n }\n`;\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\n/** A centered popup, sized like the checkout card it replaces. */\nfunction windowFeatures(): string {\n const screenWidth = window.screen?.availWidth ?? WINDOW_WIDTH;\n const screenHeight = window.screen?.availHeight ?? WINDOW_HEIGHT;\n const width = Math.min(WINDOW_WIDTH, Math.max(320, screenWidth - 40));\n const height = Math.min(WINDOW_HEIGHT, Math.max(480, screenHeight - 40));\n const baseX = typeof window.screenX === \"number\" ? window.screenX : 0;\n const baseY = typeof window.screenY === \"number\" ? window.screenY : 0;\n const outerWidth = window.outerWidth || width;\n const outerHeight = window.outerHeight || height;\n const left = Math.max(0, Math.round(baseX + (outerWidth - width) / 2));\n const top = Math.max(0, Math.round(baseY + (outerHeight - height) / 2));\n\n return [\n \"popup=yes\",\n `width=${width}`,\n `height=${height}`,\n `left=${left}`,\n `top=${top}`,\n \"resizable=yes\",\n \"scrollbars=yes\",\n ].join(\",\");\n}\n\nfunction documentHtml(\n title: string,\n dir: \"rtl\" | \"ltr\",\n lang: string,\n body: string\n): string {\n return [\n \"<!doctype html>\",\n `<html dir=\"${dir}\" lang=\"${lang}\">`,\n \"<head>\",\n '<meta charset=\"utf-8\" />',\n '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />',\n '<meta name=\"robots\" content=\"noindex\" />',\n `<title>${escapeHtml(title)}</title>`,\n `<style>${DOC_CSS}</style>`,\n \"</head>\",\n `<body>${body}</body>`,\n \"</html>\",\n ].join(\"\");\n}\n\n/**\n * Opens the hosted checkout in its own browser window.\n *\n * The window has to be requested synchronously from the buyer's click, before\n * the session request, or every popup blocker swallows it — so the constructor\n * opens a blank window with a \"preparing checkout\" page and `load()` navigates\n * it once the session exists.\n *\n * The merchant page keeps talking to the portal with `postMessage`: the window\n * handle stays valid across the navigation, and the portal answers the opener\n * (see `createEmbeddedBridge`).\n */\nexport class CheckoutWindow implements CheckoutView {\n private readonly win: Window;\n private readonly onDismiss: () => void;\n private readonly dir: \"rtl\" | \"ltr\";\n private readonly lang: string;\n private readonly title: string;\n private readonly labels: CheckoutWindowOptions[\"labels\"];\n private pollId: number | null = null;\n private navigated = false;\n private destroyed = false;\n\n onLoad: (() => void) | null = null;\n\n constructor(options: CheckoutWindowOptions) {\n const opened = window.open(\"\", WINDOW_NAME, windowFeatures());\n if (!opened) {\n throw new Error(\"The browser blocked the checkout window.\");\n }\n\n this.win = opened;\n this.onDismiss = options.onDismiss;\n this.title = options.title;\n this.labels = options.labels;\n this.dir = options.dir;\n this.lang = options.lang;\n\n this.pollId = window.setInterval(() => this.checkClosed(), CLOSE_POLL_MS);\n\n try {\n this.win.focus();\n } catch {\n // focus is best-effort in embedded browsers\n }\n }\n\n get contentWindow(): Window | null {\n return this.win;\n }\n\n open(): void {\n try {\n this.win.focus();\n } catch {\n // focus is best-effort\n }\n }\n\n load(url: string): void {\n if (this.destroyed) return;\n this.navigated = true;\n try {\n // `replace` keeps the empty window out of the buyer's back history.\n this.win.location.replace(url);\n } catch {\n if (this.win.closed) {\n this.dismiss();\n return;\n }\n // Some embedded browsers refuse one navigation call but accept another.\n try {\n this.win.location.href = url;\n } catch {\n // The portal never loaded; the close poll will notice if it is gone.\n }\n }\n this.onLoad?.();\n }\n\n showError(message: string): void {\n // After the navigation the portal owns that document; nothing safe to paint.\n if (this.destroyed || this.navigated) return;\n\n this.renderError(\n documentHtml(\n this.title,\n this.dir,\n this.lang,\n `<div class=\"panel\">` +\n `<span class=\"error-icon\" aria-hidden=\"true\">!</span>` +\n `<h2 class=\"error-title\">${escapeHtml(this.labels.errorTitle)}</h2>` +\n `<p class=\"error-message\">${escapeHtml(message)}</p>` +\n `<button class=\"error-close\" type=\"button\">${escapeHtml(this.labels.close)}</button>` +\n `</div>`\n )\n );\n\n try {\n const close = this.win.document.querySelector(\".error-close\");\n close?.addEventListener(\"click\", () => this.onDismiss());\n } catch {\n // The window went away before the close button could be wired.\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.stopPolling();\n this.onLoad = null;\n try {\n this.win.close();\n } catch {\n // Already closed by the buyer.\n }\n }\n\n /**\n * Best-effort: the placeholder document is cosmetic. A refused write must\n * never cancel the checkout — the navigation below still has to happen.\n */\n private renderError(html: string): void {\n try {\n const doc = this.win.document;\n doc.open();\n doc.write(html);\n doc.close();\n } catch {\n // Browser refused to let us paint into the blank window.\n }\n }\n\n private checkClosed(): void {\n if (this.destroyed) {\n this.stopPolling();\n return;\n }\n if (this.win.closed) this.dismiss();\n }\n\n private dismiss(): void {\n if (this.destroyed) return;\n this.stopPolling();\n this.onDismiss();\n }\n\n private stopPolling(): void {\n if (this.pollId !== null) {\n window.clearInterval(this.pollId);\n this.pollId = null;\n }\n }\n}\n","import { EsaalatCheckoutError } from \"./errors\";\nimport { CheckoutModal } from \"./modal\";\nimport type {\n CheckoutBeforeCreateOrderHandler,\n CheckoutCreatePayload,\n CheckoutItem,\n CheckoutLocale,\n CheckoutOpenOptions,\n CheckoutPresentation,\n CheckoutResult,\n CheckoutResultReason,\n CheckoutResultStatus,\n CheckoutSession,\n EsaalatCheckoutOptions,\n} from \"./types\";\nimport type { CheckoutView } from \"./view\";\nimport { CheckoutWindow } from \"./window\";\n\nconst DEFAULT_API_BASE = \"https://api.esaalat.com/api/v1\";\nconst DEFAULT_PORTAL_BASE = \"https://pay.esaalat.com\";\nconst SDK_VERSION = \"0.1.0\";\nconst REQUEST_TIMEOUT_MS = 20_000;\nconst INIT_RETRY_MS = 300;\n// A browser window needs longer than an iframe: the init message races the\n// navigation, so keep knocking until the portal answers `ready`.\nconst INIT_ATTEMPTS = 100;\nconst VERIFIED_CLOSE_MS = 1_800;\nconst ERROR_CLOSE_MS = 6_000;\n\nconst RESULT_STATUSES: CheckoutResultStatus[] = [\n \"VERIFIED\",\n \"WRONG_AMOUNT\",\n \"EXPIRED\",\n \"CANCELLED\",\n \"FAILED\",\n];\n\nconst RESULT_REASONS: CheckoutResultReason[] = [\n \"dismissed\",\n \"destroyed\",\n \"intent_cancelled\",\n \"session_expired\",\n \"session_not_found\",\n \"network_error\",\n];\n\ninterface ActiveCheckout {\n token: string | null;\n locale: CheckoutLocale;\n controller: AbortController;\n view: CheckoutView;\n settled: boolean;\n resolve: (result: CheckoutResult) => void;\n reject: (error: Error) => void;\n onResult?: (result: CheckoutResult) => void;\n}\n\ninterface PortalMessage {\n source?: unknown;\n type?: unknown;\n sessionToken?: unknown;\n payload?: unknown;\n}\n\ninterface PortalResultPayload {\n status?: unknown;\n reason?: unknown;\n intentCode?: unknown;\n amount?: unknown;\n paidAmount?: unknown;\n currency?: unknown;\n externalOrderId?: unknown;\n merchantName?: unknown;\n}\n\nfunction normalizeBase(value: string, fallback: string): string {\n const raw = value.trim() || fallback;\n let url: URL;\n try {\n const base =\n typeof window !== \"undefined\" ? window.location?.href : undefined;\n url = new URL(raw, base);\n } catch {\n throw new EsaalatCheckoutError(\n `Invalid URL: ${raw}`,\n \"configuration\"\n );\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new EsaalatCheckoutError(\n `Unsupported URL protocol: ${url.protocol}`,\n \"configuration\"\n );\n }\n return url.toString().replace(/\\/+$/, \"\");\n}\n\nfunction requestId(): string {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n // UUID v4 fallback for older embedded browsers.\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (char) => {\n const random = (Math.random() * 16) | 0;\n const value = char === \"x\" ? random : (random & 0x3) | 0x8;\n return value.toString(16);\n });\n}\n\nfunction stringOr(value: unknown, fallback = \"\"): string {\n return typeof value === \"string\" ? value : fallback;\n}\n\nfunction nullOrString(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction errorDetail(body: unknown): string | null {\n if (!body || typeof body !== \"object\") return null;\n const record = body as Record<string, unknown>;\n if (typeof record.detail === \"string\") return record.detail;\n if (Array.isArray(record.errors)) {\n for (const error of record.errors) {\n if (error && typeof error === \"object\") {\n const detail = (error as Record<string, unknown>).detail;\n if (typeof detail === \"string\") return detail;\n }\n }\n }\n for (const value of Object.values(record)) {\n if (typeof value === \"string\") return value;\n if (Array.isArray(value) && typeof value[0] === \"string\") return value[0];\n }\n return null;\n}\n\nfunction isCheckoutSession(value: unknown): value is CheckoutSession {\n if (!value || typeof value !== \"object\") return false;\n const record = value as Record<string, unknown>;\n return (\n typeof record.session_token === \"string\" &&\n typeof record.portal_url === \"string\" &&\n typeof record.amount === \"string\" &&\n typeof record.currency === \"string\"\n );\n}\n\nfunction cancelledResult(\n token: string | null,\n reason: \"dismissed\" | \"destroyed\"\n): CheckoutResult {\n return {\n status: \"CANCELLED\",\n reason,\n sessionToken: token ?? \"\",\n intentCode: null,\n amount: \"0.00\",\n paidAmount: null,\n currency: \"YER\",\n externalOrderId: \"\",\n merchantName: \"\",\n };\n}\n\n/**\n * Framework-agnostic Esaalat checkout client.\n *\n * It creates a checkout session with the merchant's publishable key, opens the\n * Esaalat-hosted portal in its own browser window (or an in-page modal when\n * asked, or when the browser blocks the window), and resolves `open()` with a\n * terminal result. The publishable key is public by design; keep the client\n * secret and any order confirmation on the server.\n */\nexport class EsaalatCheckout {\n private readonly publishableKey: string;\n private readonly apiBaseUrl: string;\n private readonly portalBaseUrl: string;\n private readonly zIndex: number;\n private readonly presentation: CheckoutPresentation;\n private readonly locale: CheckoutLocale;\n private readonly fetchImpl: typeof fetch | null;\n private readonly defaultOnResult?: (result: CheckoutResult) => void;\n private readonly defaultOnError?: (error: Error) => void;\n\n private active: ActiveCheckout | null = null;\n private view: CheckoutView | null = null;\n private portalOrigin: string | null = null;\n private sessionToken: string | null = null;\n private initTimer: number | null = null;\n private verifiedTimer: number | null = null;\n private errorTimer: number | null = null;\n\n constructor(options: EsaalatCheckoutOptions) {\n // The key is only needed to create a session in the browser. A merchant\n // that opens a server-created session passes its token instead, so an\n // empty key is allowed here and refused by `open()` only on the create\n // path.\n const key =\n typeof options?.publishableKey === \"string\"\n ? options.publishableKey.trim()\n : \"\";\n\n this.publishableKey = key;\n this.locale =\n options.locale === \"en\" || options.locale === \"ar\" ? options.locale : \"ar\";\n this.apiBaseUrl = normalizeBase(options.apiBaseUrl ?? \"\", DEFAULT_API_BASE);\n this.portalBaseUrl = normalizeBase(\n options.portalBaseUrl ?? \"\",\n DEFAULT_PORTAL_BASE\n );\n this.zIndex =\n typeof options.zIndex === \"number\" && Number.isFinite(options.zIndex)\n ? options.zIndex\n : 2_147_483_000;\n this.presentation =\n options.presentation === \"modal\" ? \"modal\" : \"window\";\n\n const fetchFromOptions = options.fetch;\n const globalFetch =\n typeof fetch === \"function\" ? fetch.bind(globalThis) : null;\n this.fetchImpl = fetchFromOptions ?? globalFetch;\n this.defaultOnResult = options.onResult;\n this.defaultOnError = options.onError;\n }\n\n /** True while a checkout window or modal is on screen. */\n get isOpen(): boolean {\n return this.view !== null;\n }\n\n /**\n * Open the hosted checkout and resolve with its terminal result.\n *\n * A second call while a checkout is open rejects; close the first one with\n * `close()` or wait for its result.\n */\n async open(options: CheckoutOpenOptions = {}): Promise<CheckoutResult> {\n if (this.active || this.view) {\n throw new EsaalatCheckoutError(\n \"A checkout is already open. Close it before starting another.\",\n \"configuration\"\n );\n }\n if (!this.fetchImpl) {\n throw new EsaalatCheckoutError(\n \"This browser does not support fetch. Use the SDK on a modern browser.\",\n \"configuration\"\n );\n }\n\n const locale =\n options.locale === \"en\" || options.locale === \"ar\"\n ? options.locale\n : this.locale;\n const items = options.items ?? [];\n const existingToken = options.sessionToken?.trim() || null;\n const hasAmount =\n options.amount !== undefined &&\n options.amount !== null &&\n String(options.amount).trim() !== \"\";\n if (!existingToken && !this.publishableKey) {\n throw new EsaalatCheckoutError(\n \"A publishable key is required to create a session. Pass one, or open a server-created `sessionToken`.\",\n \"configuration\"\n );\n }\n if (!existingToken && !hasAmount && items.length === 0) {\n throw new EsaalatCheckoutError(\n \"Provide an amount, items, or a server-created session token.\",\n \"configuration\"\n );\n }\n if (!existingToken && items.length > 0) {\n for (const item of items) {\n if (!item.name || item.price === undefined || item.price === null) {\n throw new EsaalatCheckoutError(\n \"Every item needs a name and a price.\",\n \"configuration\"\n );\n }\n }\n }\n\n const labels =\n locale === \"ar\"\n ? {\n close: \"إغلاق\",\n loading: \"جارٍ تجهيز الدفع الآمن…\",\n errorTitle: \"تعذّر بدء الدفع\",\n }\n : {\n close: \"Close\",\n loading: \"Preparing secure checkout…\",\n errorTitle: \"Couldn't start the checkout\",\n };\n\n const presentation: CheckoutPresentation =\n options.presentation === \"window\" || options.presentation === \"modal\"\n ? options.presentation\n : this.presentation;\n\n // The view is created before the first `await`: a browser window has to be\n // requested inside the buyer's click, or popup blockers discard it.\n let view: CheckoutView;\n try {\n view = this.createView(presentation, labels, locale);\n view.open();\n } catch (error) {\n throw new EsaalatCheckoutError(\n \"The checkout could not be opened.\",\n \"unavailable\",\n { cause: error }\n );\n }\n\n const controller = new AbortController();\n let resolvePromise!: (result: CheckoutResult) => void;\n let rejectPromise!: (error: Error) => void;\n const promise = new Promise<CheckoutResult>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n });\n\n const onResult = options.onResult ?? this.defaultOnResult;\n const onError = options.onError ?? this.defaultOnError;\n\n const active: ActiveCheckout = {\n token: null,\n locale,\n controller,\n view,\n settled: false,\n resolve: resolvePromise,\n reject: rejectPromise,\n onResult,\n };\n this.active = active;\n this.view = view;\n this.sessionToken = null;\n this.portalOrigin = null;\n\n view.onLoad = () => this.startInitRetry();\n\n let portalUrl: string;\n try {\n if (existingToken) {\n active.token = existingToken;\n this.sessionToken = existingToken;\n portalUrl = this.buildPortalUrl(\n existingToken,\n options.portalUrl ?? \"\",\n locale\n );\n } else {\n const session = await this.createSession(\n options,\n locale,\n controller.signal\n );\n // The buyer closed the checkout while the session was being created.\n if (active.settled) return promise;\n active.token = session.session_token;\n this.sessionToken = session.session_token;\n portalUrl = this.buildPortalUrl(\n session.session_token,\n session.portal_url,\n locale\n );\n }\n this.portalOrigin = new URL(portalUrl).origin;\n } catch (error) {\n if (active.settled) return promise;\n const wrapped =\n error instanceof EsaalatCheckoutError\n ? error\n : new EsaalatCheckoutError(\n \"Esaalat returned an invalid checkout URL.\",\n \"session\",\n { cause: error }\n );\n active.settled = true;\n this.active = null;\n this.removeMessageListener();\n try {\n onError?.(wrapped);\n } catch {\n // A merchant callback must not prevent the promise from settling.\n }\n active.reject(wrapped);\n view.showError(wrapped.message);\n this.errorTimer = window.setTimeout(() => {\n if (this.view === view) this.teardown();\n }, ERROR_CLOSE_MS);\n return promise;\n }\n\n window.addEventListener(\"message\", this.handleMessage);\n view.load(portalUrl);\n return promise;\n }\n\n /** Close the checkout. An in-flight `open()` resolves with CANCELLED. */\n close(): void {\n if (this.active) {\n this.dismiss();\n return;\n }\n this.teardown();\n }\n\n /** Remove the checkout view and any listeners without resolving a result. */\n destroy(): void {\n if (this.active && !this.active.settled) {\n this.finish(cancelledResult(this.sessionToken, \"destroyed\"));\n return;\n }\n this.teardown();\n }\n\n private createView(\n presentation: CheckoutPresentation,\n labels: { close: string; loading: string; errorTitle: string },\n locale: CheckoutLocale\n ): CheckoutView {\n const title =\n locale === \"ar\" ? \"إيصالات — دفع آمن\" : \"Esaalat — Secure checkout\";\n const onDismiss = () => this.dismiss();\n\n if (presentation === \"window\") {\n try {\n return new CheckoutWindow({\n title,\n labels,\n dir: locale === \"ar\" ? \"rtl\" : \"ltr\",\n lang: locale,\n onDismiss,\n });\n } catch {\n // The popup was blocked (or there is no window): the modal is the\n // always-available fallback, so the buyer still gets to pay.\n }\n }\n\n return new CheckoutModal({\n zIndex: this.zIndex,\n title,\n labels,\n onDismiss,\n });\n }\n\n private buildPortalUrl(\n sessionToken: string,\n rawPortalUrl: string,\n locale: CheckoutLocale\n ): string {\n const raw =\n rawPortalUrl.trim() ||\n `${this.portalBaseUrl}/checkout/${encodeURIComponent(sessionToken)}`;\n const url = new URL(raw);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new Error(\"Unsupported portal protocol\");\n }\n url.searchParams.set(\"lang\", locale);\n return url.toString();\n }\n\n private async createSession(\n options: CheckoutOpenOptions,\n locale: CheckoutLocale,\n outerSignal: AbortSignal\n ): Promise<CheckoutSession> {\n if (!this.fetchImpl) {\n throw new EsaalatCheckoutError(\"fetch is unavailable\", \"configuration\");\n }\n\n let payload: CheckoutCreatePayload = {};\n if (options.amount !== undefined && options.amount !== null) {\n payload.amount = String(options.amount);\n }\n if (options.items?.length) {\n payload.items = options.items.map((item: CheckoutItem) => ({\n name: item.name,\n ...(item.description ? { description: item.description } : {}),\n price: String(item.price),\n quantity: item.quantity ?? 1,\n }));\n }\n if (options.currency) payload.currency = options.currency;\n if (options.externalOrderId) {\n payload.external_order_id = options.externalOrderId;\n }\n if (options.notes) payload.notes = options.notes;\n if (options.wallet) payload.wallet = options.wallet;\n\n // The merchant's last word on what is sent. Whatever this throws becomes\n // the checkout's own error, so a veto reaches `open()` as `configuration`\n // with the merchant's message instead of being swallowed.\n const beforeCreate: CheckoutBeforeCreateOrderHandler | undefined =\n options.onBeforeCreateOrder;\n if (beforeCreate) {\n let updated: CheckoutCreatePayload | void;\n try {\n updated = await beforeCreate(payload);\n } catch (error) {\n throw new EsaalatCheckoutError(\n error instanceof Error && error.message\n ? error.message\n : locale === \"ar\"\n ? \"أُلغي الدفع.\"\n : \"The checkout was cancelled.\",\n \"configuration\",\n { cause: error }\n );\n }\n if (updated && typeof updated === \"object\") payload = updated;\n }\n\n const controller = new AbortController();\n let timedOut = false;\n const timeout = window.setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, REQUEST_TIMEOUT_MS);\n const abortOuter = () => controller.abort();\n outerSignal.addEventListener(\"abort\", abortOuter);\n\n try {\n const response = await this.fetchImpl(\n `${this.apiBaseUrl}/checkout/sdk/sessions/`,\n {\n method: \"POST\",\n credentials: \"omit\",\n cache: \"no-store\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n \"ESAALAT-PUBLISHABLE-KEY\": this.publishableKey,\n \"ESAALAT-IDEMPOTENCY-KEY\":\n options.idempotencyKey?.trim() || requestId(),\n \"ESAALAT-SDK-VERSION\": SDK_VERSION,\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n }\n );\n\n const session: unknown = await response.json().catch(() => null);\n if (!response.ok) {\n throw new EsaalatCheckoutError(\n errorDetail(session) ||\n (locale === \"ar\"\n ? \"تعذّر إنشاء جلسة الدفع.\"\n : \"Couldn't create the checkout session.\"),\n \"api\",\n { status: response.status, details: session }\n );\n }\n if (!isCheckoutSession(session)) {\n throw new EsaalatCheckoutError(\n \"Esaalat returned an invalid checkout session.\",\n \"session\",\n { details: session }\n );\n }\n\n // The session exists; a broken listener must not kill the payment.\n try {\n options.onOrderCreated?.(session);\n } catch {\n // Ignored on purpose.\n }\n\n return session;\n } catch (error) {\n if (error instanceof EsaalatCheckoutError) throw error;\n if (timedOut) {\n throw new EsaalatCheckoutError(\n locale === \"ar\"\n ? \"انتهت مهلة الاتصال بإيصالات. حاول مرة أخرى.\"\n : \"The connection to Esaalat timed out. Please try again.\",\n \"network\",\n { cause: error }\n );\n }\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw error;\n }\n throw new EsaalatCheckoutError(\n locale === \"ar\"\n ? \"تعذّر الاتصال بإيصالات. تحقق من اتصالك وحاول مرة أخرى.\"\n : \"Couldn't reach Esaalat. Check your connection and try again.\",\n \"network\",\n { cause: error }\n );\n } finally {\n window.clearTimeout(timeout);\n outerSignal.removeEventListener(\"abort\", abortOuter);\n }\n }\n\n private startInitRetry(): void {\n this.clearInitTimer();\n let attempts = 0;\n\n const tick = () => {\n if (!this.view || !this.portalOrigin || !this.sessionToken) return;\n this.postInit();\n attempts += 1;\n if (attempts < INIT_ATTEMPTS) {\n this.initTimer = window.setTimeout(tick, INIT_RETRY_MS);\n } else {\n this.initTimer = null;\n }\n };\n\n tick();\n }\n\n private postInit(): void {\n const target = this.view?.contentWindow;\n if (!target || !this.portalOrigin || !this.sessionToken) return;\n const message = {\n source: \"esaalat-checkout-sdk\",\n version: 1,\n type: \"init\",\n sessionToken: this.sessionToken,\n parentOrigin: window.location.origin,\n locale: this.active?.locale ?? this.locale,\n };\n try {\n target.postMessage(message, this.portalOrigin);\n } catch {\n // The iframe may have been torn down between the check and the post.\n }\n }\n\n private clearInitTimer(): void {\n if (this.initTimer !== null) {\n window.clearTimeout(this.initTimer);\n this.initTimer = null;\n }\n }\n\n private handleMessage = (event: MessageEvent): void => {\n if (!this.view || !this.portalOrigin) return;\n if (event.source !== this.view.contentWindow) return;\n if (event.origin !== this.portalOrigin) return;\n\n const data = event.data as PortalMessage | null;\n if (!data || typeof data !== \"object\") return;\n if (data.source !== \"esaalat-checkout\") return;\n if (data.sessionToken !== this.sessionToken) return;\n\n if (data.type === \"ready\") {\n this.clearInitTimer();\n return;\n }\n\n if (data.type === \"close\") {\n this.dismiss();\n return;\n }\n\n if (data.type === \"result\") {\n const result = this.parseResult(data.payload);\n if (result) this.finish(result);\n }\n };\n\n private parseResult(payload: unknown): CheckoutResult | null {\n if (!payload || typeof payload !== \"object\") return null;\n const value = payload as PortalResultPayload;\n if (\n typeof value.status !== \"string\" ||\n !RESULT_STATUSES.includes(value.status as CheckoutResultStatus)\n ) {\n return null;\n }\n\n const reason =\n typeof value.reason === \"string\" &&\n RESULT_REASONS.includes(value.reason as CheckoutResultReason)\n ? (value.reason as CheckoutResultReason)\n : undefined;\n\n return {\n status: value.status as CheckoutResultStatus,\n ...(reason ? { reason } : {}),\n sessionToken: this.sessionToken ?? \"\",\n intentCode: nullOrString(value.intentCode),\n amount: stringOr(value.amount, \"0.00\"),\n paidAmount: nullOrString(value.paidAmount),\n currency: stringOr(value.currency, \"YER\"),\n externalOrderId: stringOr(value.externalOrderId),\n merchantName: stringOr(value.merchantName),\n };\n }\n\n private finish(result: CheckoutResult): void {\n const active = this.active;\n if (!active || active.settled) return;\n\n active.settled = true;\n this.active = null;\n this.clearInitTimer();\n active.controller.abort();\n try {\n active.onResult?.(result);\n } catch {\n // A merchant callback must not prevent the promise from settling.\n }\n active.resolve(result);\n\n if (result.reason === \"dismissed\" || result.reason === \"destroyed\") {\n this.teardown();\n return;\n }\n\n if (result.status === \"VERIFIED\") {\n this.verifiedTimer = window.setTimeout(() => this.teardown(), VERIFIED_CLOSE_MS);\n }\n // Other terminal states stay visible until the buyer closes them, so the\n // reason (wrong amount, expiry, cancellation) is not flashed away.\n }\n\n private dismiss(): void {\n if (this.active && !this.active.settled) {\n this.finish(cancelledResult(this.sessionToken, \"dismissed\"));\n return;\n }\n this.teardown();\n }\n\n private removeMessageListener(): void {\n window.removeEventListener(\"message\", this.handleMessage);\n }\n\n private clearTimers(): void {\n this.clearInitTimer();\n if (this.verifiedTimer !== null) {\n window.clearTimeout(this.verifiedTimer);\n this.verifiedTimer = null;\n }\n if (this.errorTimer !== null) {\n window.clearTimeout(this.errorTimer);\n this.errorTimer = null;\n }\n }\n\n private teardown(): void {\n this.clearTimers();\n this.removeMessageListener();\n if (this.view) {\n this.view.destroy();\n this.view = null;\n }\n this.portalOrigin = null;\n this.sessionToken = null;\n this.active = null;\n }\n}\n","import { EsaalatCheckout } from \"./client\";\nimport { EsaalatCheckoutError } from \"./errors\";\nimport type {\n CheckoutBeforeCreateOrderHandler,\n CheckoutItem,\n CheckoutLocale,\n CheckoutOpenOptions,\n CheckoutPresentation,\n CheckoutResult,\n CheckoutResultStatus,\n CheckoutSession,\n} from \"./types\";\n\n/**\n * A \"Pay with Esaalat\" button that any framework can render.\n *\n * It is a custom element, not a React/Vue/Angular component, because the\n * checkout is one behaviour that should not be reimplemented per framework:\n * the same tag and the same attributes work in plain HTML, in a Vue template\n * (`@esaalat-verified`), in an Angular template (`(esaalat-verified)` with\n * `CUSTOM_ELEMENTS_SCHEMA`) and — through `esaalat-react`, which only sets\n * properties and listeners — in JSX.\n *\n * The element is a thin shell over `EsaalatCheckout`: a click calls `open()`\n * with the attributes as options, and the terminal result is routed to ONE\n * named callback per outcome (see `OUTCOMES`). Nothing here re-implements the\n * portal, the session API or the result contract.\n *\n * ```html\n * <esaalat-checkout-button\n * publishable-key=\"pk_live_...\"\n * amount=\"5000.00\"\n * external-order-id=\"order-123\"\n * ></esaalat-checkout-button>\n * <script>\n * const button = document.querySelector(\"esaalat-checkout-button\");\n * button.onVerified = (result) => console.log(result.intentCode);\n * button.onCancelled = () => console.log(\"not this time\");\n * </script>\n * ```\n */\n\n/** The tag this element is registered under. */\nexport const ESAALAT_CHECKOUT_BUTTON_TAG = \"esaalat-checkout-button\";\n\n/** Label shown when the merchant passes neither `label` nor child text. */\nconst DEFAULT_LABELS: Record<CheckoutLocale, string> = {\n ar: \"ادفع الآن\",\n en: \"Pay now\",\n};\n\ntype HandlerName =\n | \"onVerified\"\n | \"onCancelled\"\n | \"onWrongAmount\"\n | \"onExpired\"\n | \"onFailed\";\n\n/**\n * One callback per terminal status: the buyer's outcome picks exactly one row,\n * so a merchant never has to switch on `result.status` to find the interesting\n * case. `FAILED` is a result (the portal could not load a valid session), not a\n * thrown error — `onError` stays reserved for `open()` rejecting.\n */\nconst OUTCOMES: Record<\n CheckoutResultStatus,\n { handler: HandlerName; event: string }\n> = {\n VERIFIED: { handler: \"onVerified\", event: \"esaalat-verified\" },\n CANCELLED: { handler: \"onCancelled\", event: \"esaalat-cancelled\" },\n WRONG_AMOUNT: { handler: \"onWrongAmount\", event: \"esaalat-wrong-amount\" },\n EXPIRED: { handler: \"onExpired\", event: \"esaalat-expired\" },\n FAILED: { handler: \"onFailed\", event: \"esaalat-failed\" },\n};\n\n/** Names of the DOM events, exported for `addEventListener` users. */\nexport const ESAALAT_CHECKOUT_EVENTS = {\n verified: \"esaalat-verified\",\n cancelled: \"esaalat-cancelled\",\n wrongAmount: \"esaalat-wrong-amount\",\n expired: \"esaalat-expired\",\n failed: \"esaalat-failed\",\n error: \"esaalat-error\",\n} as const;\n\n/** How often the button re-checks whether its checkout has been closed. */\nconst WATCH_INTERVAL_MS = 300;\n\nfunction asError(error: unknown): Error {\n if (error instanceof Error) return error;\n return new EsaalatCheckoutError(String(error) || \"The checkout failed.\", \"unavailable\");\n}\n\nexport class EsaalatCheckoutButtonElement extends HTMLElement {\n static get observedAttributes(): string[] {\n return [\n \"publishable-key\",\n \"amount\",\n \"currency\",\n \"external-order-id\",\n \"notes\",\n \"wallet\",\n \"locale\",\n \"presentation\",\n \"session-token\",\n \"portal-url\",\n \"label\",\n \"disabled\",\n \"items\",\n ];\n }\n\n /** Called with the result when the wallet alert verified the payment. */\n onVerified?: (result: CheckoutResult) => void;\n /** Called when the buyer dismissed the checkout, or the intent was cancelled. */\n onCancelled?: (result: CheckoutResult) => void;\n /** Called when a payment matched but for a different amount. */\n onWrongAmount?: (result: CheckoutResult) => void;\n /** Called when the buyer ran out of time. */\n onExpired?: (result: CheckoutResult) => void;\n /** Called when the portal could not load a valid session. */\n onFailed?: (result: CheckoutResult) => void;\n /** Called when `open()` rejects (configuration, network, API or unavailable). */\n onError?: (error: Error) => void;\n\n /**\n * Called just before this button creates the session in the browser, with\n * the body about to be sent. Return an object to add or override fields\n * (`external_order_id`, `notes`, anything your API accepts); throwing\n * cancels the checkout and reports the message via `onError`.\n */\n onBeforeCreateOrder?: CheckoutBeforeCreateOrderHandler;\n\n /**\n * Called with the created session (token, intent, expiry...) when this\n * button created it in the browser. Not called when a `session-token`\n * attribute is set, because that session was made on your server.\n */\n onOrderCreated?: (session: CheckoutSession) => void;\n\n /**\n * Order lines as data. The `items` attribute carries the same as JSON, for\n * HTML templates that have no way to set a property.\n */\n items: CheckoutItem[] | null = null;\n\n private client: EsaalatCheckout | null = null;\n private clientKey: string | null = null;\n private button: HTMLButtonElement | null = null;\n private busy = false;\n private watchTimer: ReturnType<typeof setInterval> | null = null;\n /** Text written between the tags, captured before the button is injected. */\n private slotLabel: string | null = null;\n\n connectedCallback(): void {\n this.render();\n }\n\n disconnectedCallback(): void {\n // The checkout itself lives on `document.body`, so a removed button must\n // not cancel a payment in progress. Only the state watcher goes away.\n this.stopWatch();\n }\n\n attributeChangedCallback(\n name: string,\n previous: string | null,\n value: string | null\n ): void {\n if (previous === value) return;\n\n if (name === \"publishable-key\") {\n // A different key means a different client; the next click builds it.\n this.client = null;\n this.clientKey = null;\n return;\n }\n if (name === \"label\" || name === \"locale\") {\n this.applyLabel();\n return;\n }\n if (name === \"disabled\") {\n this.syncBusy();\n }\n }\n\n /** Open the checkout, exactly as a click does (for programmatic use). */\n async open(): Promise<void> {\n await this.start();\n }\n\n private handleClick = (): void => {\n // Not awaited: the click task must keep running synchronously so the\n // browser-window presentation is still inside the buyer's gesture.\n void this.start();\n };\n\n private async start(): Promise<void> {\n if (this.busy || this.isCheckoutOpen()) return;\n\n const key = (this.getAttribute(\"publishable-key\") ?? \"\").trim();\n // A `session-token` already names the checkout; the key only creates one.\n if (!key && !this.attribute(\"session-token\")) {\n this.reportError(\n new EsaalatCheckoutError(\"A publishable key is required.\", \"configuration\")\n );\n return;\n }\n\n this.setBusy(true);\n this.watch();\n\n try {\n const items = this.readItems();\n const client = this.ensureClient(key);\n const result = await client.open(this.openOptions(items));\n this.handleResult(result);\n } catch (error) {\n this.reportError(asError(error));\n } finally {\n this.setBusy(false);\n }\n }\n\n private ensureClient(key: string): EsaalatCheckout {\n if (this.client && this.clientKey === key) return this.client;\n // Replacing the client only happens when the key changes. It has no open\n // checkout to lose: `start()` refuses to run while one is on screen.\n this.clientKey = key;\n this.client = new EsaalatCheckout({\n publishableKey: key,\n locale: this.locale(),\n });\n return this.client;\n }\n\n private openOptions(items: CheckoutItem[] | null): CheckoutOpenOptions {\n return {\n amount: this.attribute(\"amount\"),\n items: items ?? undefined,\n currency: this.attribute(\"currency\"),\n externalOrderId: this.attribute(\"external-order-id\"),\n notes: this.attribute(\"notes\"),\n wallet: this.attribute(\"wallet\"),\n sessionToken: this.attribute(\"session-token\"),\n portalUrl: this.attribute(\"portal-url\"),\n locale: this.locale(),\n presentation: this.presentation(),\n onBeforeCreateOrder: this.onBeforeCreateOrder,\n onOrderCreated: this.onOrderCreated,\n };\n }\n\n private handleResult(result: CheckoutResult): void {\n const outcome = OUTCOMES[result.status];\n if (!outcome) return;\n\n // The status is the single source of truth: only the matching callback\n // runs, so a merchant can wire all five without guarding each one.\n this.callSafely(this[outcome.handler] as ((r: CheckoutResult) => void) | undefined, result);\n this.dispatchOutcome(outcome.event, result);\n }\n\n private reportError(error: Error): void {\n this.callSafely(this.onError, error);\n this.dispatchOutcome(ESAALAT_CHECKOUT_EVENTS.error, error);\n }\n\n /**\n * DOM events carry the same detail as the callbacks, so templates that bind\n * events instead of properties (`@esaalat-verified`, `(esaalat-verified)`)\n * need no extra JS.\n */\n private dispatchOutcome(name: string, detail: CheckoutResult | Error): void {\n this.dispatchEvent(\n new CustomEvent(name, { detail, bubbles: true, composed: true })\n );\n }\n\n private callSafely<Arg>(handler: ((argument: Arg) => void) | undefined, argument: Arg): void {\n if (!handler) return;\n try {\n handler(argument);\n } catch {\n // A merchant callback must never break the element's own bookkeeping.\n }\n }\n\n private readItems(): CheckoutItem[] | null {\n if (this.items && this.items.length > 0) return this.items;\n\n const raw = this.attribute(\"items\");\n if (!raw) return null;\n try {\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) throw new Error(\"not an array\");\n return parsed as CheckoutItem[];\n } catch {\n throw new EsaalatCheckoutError(\n \"The items attribute must be a JSON array of order lines.\",\n \"configuration\"\n );\n }\n }\n\n private attribute(name: string): string | undefined {\n const value = (this.getAttribute(name) ?? \"\").trim();\n return value || undefined;\n }\n\n private locale(): CheckoutLocale {\n return this.getAttribute(\"locale\") === \"en\" ? \"en\" : \"ar\";\n }\n\n private presentation(): CheckoutPresentation {\n // A component implies in-page, so the modal is the default here even\n // though the imperative client opens a browser window by default.\n return this.getAttribute(\"presentation\") === \"window\" ? \"window\" : \"modal\";\n }\n\n private isCheckoutOpen(): boolean {\n return this.client?.isOpen ?? false;\n }\n\n // -- rendering -----------------------------------------------------------\n\n private render(): void {\n if (!this.button) {\n // Read any \"Pay now\" written between the tags before the button exists,\n // so `<esaalat-checkout-button>Pay</esaalat-checkout-button>` works.\n if (this.slotLabel === null) {\n this.slotLabel = (this.textContent ?? \"\").trim();\n }\n\n const button = this.ownerDocument.createElement(\"button\");\n button.type = \"button\";\n button.className = \"esaalat-checkout-button\";\n button.addEventListener(\"click\", this.handleClick);\n this.replaceChildren(button);\n this.button = button;\n this.applyStyles(button);\n }\n this.applyLabel();\n this.syncBusy();\n }\n\n private applyLabel(): void {\n if (!this.button) return;\n const label =\n this.attribute(\"label\") ??\n (this.slotLabel || undefined) ??\n DEFAULT_LABELS[this.locale()];\n this.button.textContent = label;\n }\n\n /**\n * Defaults live on the inner button and read CSS custom properties, so a\n * merchant themes the control from their own stylesheet without the element\n * shipping a global stylesheet or a shadow root that would trap their CSS.\n */\n private applyStyles(button: HTMLButtonElement): void {\n button.style.appearance = \"none\";\n button.style.border =\n \"1px solid var(--esaalat-button-border, transparent)\";\n button.style.borderRadius = \"var(--esaalat-button-radius, 12px)\";\n button.style.background = \"var(--esaalat-button-background, #1f2a24)\";\n button.style.color = \"var(--esaalat-button-color, #ffffff)\";\n button.style.font = \"inherit\";\n button.style.fontSize = \"var(--esaalat-button-font-size, 15px)\";\n button.style.fontWeight = \"600\";\n button.style.lineHeight = \"1.2\";\n button.style.padding = \"var(--esaalat-button-padding, 14px 22px)\";\n button.style.cursor = \"pointer\";\n button.style.transition = \"opacity 120ms ease-out\";\n }\n\n private setBusy(busy: boolean): void {\n this.busy = busy;\n this.syncBusy();\n }\n\n private syncBusy(): void {\n if (!this.button) return;\n const busy = this.busy || this.isCheckoutOpen();\n // `disabled` always locks the button; otherwise it is locked only while\n // this element is the one driving a checkout.\n const locked = busy || this.hasAttribute(\"disabled\");\n this.button.disabled = locked;\n this.button.setAttribute(\"aria-busy\", busy ? \"true\" : \"false\");\n this.button.style.opacity = this.hasAttribute(\"disabled\") && !busy ? \"0.6\" : \"1\";\n this.button.style.cursor = locked ? \"default\" : \"pointer\";\n }\n\n // -- state watcher -------------------------------------------------------\n\n /**\n * A result resolves `open()`, but the portal stays on screen for a moment\n * (`VERIFIED` auto-closes; every other outcome waits for the buyer to close\n * it). The button has to stay locked until then — a click in that window\n * would only reach \"a checkout is already open\".\n */\n private watch(): void {\n if (this.watchTimer !== null || typeof setInterval !== \"function\") return;\n this.watchTimer = setInterval(() => {\n // `busy` covers the window before the portal has loaded (a slow session\n // request): the checkout is not open yet, but the watch is still needed\n // for when it closes afterwards.\n if (!this.busy && !this.isCheckoutOpen()) this.stopWatch();\n this.syncBusy();\n }, WATCH_INTERVAL_MS);\n }\n\n private stopWatch(): void {\n if (this.watchTimer === null) return;\n clearInterval(this.watchTimer);\n this.watchTimer = null;\n }\n}\n\n/**\n * Define `<esaalat-checkout-button>`. Safe to call repeatedly and on the\n * server (no `customElements`), so a bundler can import this module during\n * SSR without a guard of its own.\n *\n * Returns whether this call defined the element.\n */\nexport function registerEsaalatCheckoutButton(): boolean {\n if (typeof customElements === \"undefined\") return false;\n if (customElements.get(ESAALAT_CHECKOUT_BUTTON_TAG)) return false;\n customElements.define(ESAALAT_CHECKOUT_BUTTON_TAG, EsaalatCheckoutButtonElement);\n return true;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [ESAALAT_CHECKOUT_BUTTON_TAG]: EsaalatCheckoutButtonElement;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/modal.ts","../src/window.ts","../src/client.ts","../src/element.ts"],"sourcesContent":["export { EsaalatCheckout } from \"./client\";\nexport {\n ESAALAT_CHECKOUT_BUTTON_TAG,\n ESAALAT_CHECKOUT_EVENTS,\n EsaalatCheckoutButtonElement,\n registerEsaalatCheckoutButton,\n} from \"./element\";\nexport { EsaalatCheckoutError } from \"./errors\";\nexport type { CheckoutErrorCode } from \"./errors\";\nexport type {\n CheckoutBeforeCreateOrderHandler,\n CheckoutCreatePayload,\n CheckoutItem,\n CheckoutIntent,\n CheckoutLocale,\n CheckoutOpenOptions,\n CheckoutPresentation,\n CheckoutProvider,\n CheckoutResult,\n CheckoutResultReason,\n CheckoutResultStatus,\n CheckoutSession,\n CheckoutWallet,\n EsaalatCheckoutOptions,\n ExpectedReferenceType,\n} from \"./types\";\n\nexport { EsaalatCheckout as default } from \"./client\";\n","export type CheckoutErrorCode =\n | \"configuration\"\n | \"network\"\n | \"api\"\n | \"session\"\n | \"unavailable\"\n | \"aborted\";\n\nexport class EsaalatCheckoutError extends Error {\n readonly code: CheckoutErrorCode;\n readonly status?: number;\n readonly details?: unknown;\n\n constructor(\n message: string,\n code: CheckoutErrorCode,\n options: { status?: number; details?: unknown; cause?: unknown } = {}\n ) {\n super(message);\n this.name = \"EsaalatCheckoutError\";\n this.code = code;\n this.status = options.status;\n this.details = options.details;\n if (options.cause !== undefined) {\n // `cause` is ES2022; assigning it keeps the package ES2020-compatible.\n (this as Error & { cause?: unknown }).cause = options.cause;\n }\n }\n}\n","import type { CheckoutView } from \"./view\";\n\nexport interface CheckoutModalLabels {\n close: string;\n loading: string;\n errorTitle: string;\n}\n\ninterface CheckoutModalOptions {\n zIndex: number;\n title: string;\n labels: CheckoutModalLabels;\n onDismiss: () => void;\n}\n\nconst MODAL_CSS = `\n :host { all: initial; }\n *, *::before, *::after { box-sizing: border-box; }\n .overlay {\n position: fixed;\n inset: 0;\n z-index: 0;\n display: grid;\n place-items: center;\n padding: 12px;\n background: rgba(12, 11, 8, 0.58);\n -webkit-backdrop-filter: blur(7px);\n backdrop-filter: blur(7px);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n color: #0b0b0b;\n pointer-events: auto;\n animation: fade 180ms ease-out;\n }\n .dialog {\n position: relative;\n width: min(460px, calc(100vw - 24px));\n height: min(720px, calc(100dvh - 24px));\n overflow: hidden;\n border-radius: 22px;\n background: #fffefa;\n border: 1px solid rgba(255, 255, 255, 0.5);\n box-shadow: 0 36px 100px rgba(0, 0, 0, 0.4), 0 6px 24px rgba(0, 0, 0, 0.2);\n animation: rise 220ms cubic-bezier(0.2, 0.8, 0.2, 1);\n }\n .dialog.is-frame { background: #f3f0e8; }\n .chrome {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 14px 16px;\n border-bottom: 1px solid #e7e2d7;\n background: #fffefa;\n }\n .dialog.is-frame .chrome { display: none; }\n .mark {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n display: grid;\n place-items: center;\n background: #0b0b0b;\n color: #fff;\n font-size: 14px;\n font-weight: 800;\n flex-shrink: 0;\n }\n .chrome-title {\n font-size: 13px;\n font-weight: 700;\n line-height: 1.3;\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .close {\n width: 32px;\n height: 32px;\n display: grid;\n place-items: center;\n border: 0;\n border-radius: 9px;\n background: transparent;\n color: #716f67;\n cursor: pointer;\n flex-shrink: 0;\n }\n .close:hover { background: #f3f0e8; color: #0b0b0b; }\n .close:focus-visible { outline: 2px solid #0b0b0b; outline-offset: 2px; }\n .close svg { width: 18px; height: 18px; }\n .content {\n position: absolute;\n inset: 57px 0 0;\n overflow: hidden;\n }\n .dialog.is-frame .content { inset: 0; }\n .frame {\n display: block;\n width: 100%;\n height: 100%;\n border: 0;\n background: #f3f0e8;\n }\n .panel {\n height: 100%;\n display: grid;\n place-content: center;\n justify-items: center;\n gap: 12px;\n padding: 32px;\n text-align: center;\n }\n .spinner {\n width: 34px;\n height: 34px;\n border-radius: 50%;\n border: 2px solid #e7e2d7;\n border-top-color: #0b0b0b;\n animation: spin 900ms linear infinite;\n }\n .loading { font-size: 13px; color: #716f67; }\n .error-icon {\n width: 54px;\n height: 54px;\n border-radius: 50%;\n display: grid;\n place-items: center;\n background: #fef1ef;\n border: 1px solid #f5cfca;\n color: #b42318;\n }\n .error-icon svg { width: 25px; height: 25px; }\n .error-title { margin: 0; font-size: 17px; line-height: 1.4; }\n .error-message { margin: 0; font-size: 13px; line-height: 1.7; color: #716f67; max-width: 34ch; }\n .error-close {\n margin-top: 6px;\n min-height: 42px;\n padding: 9px 22px;\n border: 1px solid #e7e2d7;\n border-radius: 11px;\n background: transparent;\n color: #0b0b0b;\n font: inherit;\n font-size: 13px;\n font-weight: 700;\n cursor: pointer;\n }\n .error-close:hover { background: #f3f0e8; }\n .error-close:focus-visible { outline: 2px solid #0b0b0b; outline-offset: 2px; }\n @keyframes spin { to { transform: rotate(360deg); } }\n @keyframes fade { from { opacity: 0; } }\n @keyframes rise { from { opacity: 0; transform: translateY(10px) scale(0.985); } }\n @media (max-width: 520px) {\n .overlay { padding: 0; }\n .dialog {\n width: 100vw;\n height: 100dvh;\n max-height: none;\n border-radius: 0;\n border: 0;\n }\n .chrome { padding-top: calc(14px + env(safe-area-inset-top)); }\n }\n @media (prefers-color-scheme: dark) {\n .overlay { background: rgba(0, 0, 0, 0.7); }\n .dialog, .chrome { background: #1d1b17; border-color: #343028; color: #f6f2e8; }\n .dialog.is-frame, .frame { background: #141310; }\n .chrome-title { color: #f6f2e8; }\n .close { color: #aaa59a; }\n .close:hover { background: #2b2721; color: #f6f2e8; }\n .spinner { border-color: #343028; border-top-color: #f6f2e8; }\n .loading, .error-message { color: #aaa59a; }\n .error-icon { background: #2b1b19; border-color: #4b2c28; color: #f18d83; }\n .error-close { border-color: #343028; color: #f6f2e8; }\n .error-close:hover { background: #2b2721; }\n }\n @media (prefers-reduced-motion: reduce) {\n .overlay, .dialog { animation: none; }\n .spinner { animation-duration: 0.01ms; }\n }\n`;\n\nfunction element<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n className?: string\n): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n if (className) node.className = className;\n return node;\n}\n\nfunction closeSvg(): SVGSVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"1.8\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", \"M18 6 6 18M6 6l12 12\");\n svg.append(path);\n return svg;\n}\n\nfunction alertSvg(): SVGSVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"1.8\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", \"M12 9v4M12 17h.01M10.3 3.9 2.5 17.4A2 2 0 0 0 4.2 20h15.6a2 2 0 0 0 1.7-2.6L13.7 3.9a2 2 0 0 0-3.4 0Z\");\n svg.append(path);\n return svg;\n}\n\n/**\n * The modal lives in a shadow root so a merchant's global CSS cannot leak into\n * the checkout (or the other way around). The iframe is the only content once\n * the session is ready; the portal owns its own close button.\n */\nexport class CheckoutModal implements CheckoutView {\n private readonly host: HTMLDivElement;\n private readonly shadow: ShadowRoot;\n private readonly overlay: HTMLDivElement;\n private readonly dialog: HTMLDivElement;\n private readonly closeButton: HTMLButtonElement;\n private readonly content: HTMLDivElement;\n private frame: HTMLIFrameElement | null = null;\n private previousOverflow = \"\";\n private previousFocus: Element | null = null;\n private destroyed = false;\n\n onLoad: (() => void) | null = null;\n private readonly onDismiss: () => void;\n\n constructor(private readonly options: CheckoutModalOptions) {\n this.onDismiss = options.onDismiss;\n\n this.host = document.createElement(\"div\");\n this.host.setAttribute(\"data-esaalat-checkout\", \"\");\n this.host.style.cssText = `all: initial; position: fixed; inset: 0; z-index: ${options.zIndex}; pointer-events: none;`;\n\n this.shadow = this.host.attachShadow({ mode: \"open\" });\n const style = element(\"style\");\n style.textContent = MODAL_CSS;\n this.shadow.append(style);\n\n this.overlay = element(\"div\", \"overlay\");\n this.overlay.addEventListener(\"mousedown\", (event) => {\n if (event.target === this.overlay) this.onDismiss();\n });\n\n this.dialog = element(\"div\", \"dialog\");\n this.dialog.setAttribute(\"role\", \"dialog\");\n this.dialog.setAttribute(\"aria-modal\", \"true\");\n this.dialog.setAttribute(\"aria-label\", options.title);\n\n const chrome = element(\"div\", \"chrome\");\n const mark = element(\"span\", \"mark\");\n mark.textContent = \"E\";\n mark.setAttribute(\"aria-hidden\", \"true\");\n const title = element(\"span\", \"chrome-title\");\n title.textContent = options.title;\n\n this.closeButton = element(\"button\", \"close\");\n this.closeButton.type = \"button\";\n this.closeButton.setAttribute(\"aria-label\", options.labels.close);\n this.closeButton.append(closeSvg());\n this.closeButton.addEventListener(\"click\", () => this.onDismiss());\n\n chrome.append(mark, title, this.closeButton);\n\n this.content = element(\"div\", \"content\");\n this.showLoading();\n\n this.dialog.append(chrome, this.content);\n this.overlay.append(this.dialog);\n this.shadow.append(this.overlay);\n }\n\n open(): void {\n if (!document.body) {\n throw new Error(\"Esaalat checkout needs a document body.\");\n }\n this.previousOverflow = document.body.style.overflow;\n this.previousFocus = document.activeElement;\n document.body.style.overflow = \"hidden\";\n document.body.append(this.host);\n document.addEventListener(\"keydown\", this.handleKeyDown, true);\n this.closeButton.focus({ preventScroll: true });\n }\n\n load(url: string): void {\n if (this.destroyed) return;\n this.dialog.classList.add(\"is-frame\");\n this.content.replaceChildren();\n\n const frame = document.createElement(\"iframe\");\n frame.className = \"frame\";\n frame.src = url;\n frame.title = this.options.title;\n frame.setAttribute(\"allow\", \"clipboard-write\");\n frame.setAttribute(\"referrerpolicy\", \"strict-origin-when-cross-origin\");\n frame.setAttribute(\"loading\", \"eager\");\n frame.addEventListener(\"load\", () => {\n this.onLoad?.();\n try {\n frame.focus({ preventScroll: true });\n } catch {\n // focus is best-effort in embedded browsers\n }\n });\n\n this.frame = frame;\n this.content.append(frame);\n }\n\n get contentWindow(): Window | null {\n return this.frame?.contentWindow ?? null;\n }\n\n showError(message: string): void {\n if (this.destroyed) return;\n this.content.replaceChildren();\n\n const panel = element(\"div\", \"panel\");\n const icon = element(\"span\", \"error-icon\");\n icon.append(alertSvg());\n const title = element(\"h2\", \"error-title\");\n title.textContent = this.options.labels.errorTitle;\n const text = element(\"p\", \"error-message\");\n text.textContent = message;\n const close = element(\"button\", \"error-close\");\n close.type = \"button\";\n close.textContent = this.options.labels.close;\n close.addEventListener(\"click\", () => this.onDismiss());\n\n panel.append(icon, title, text, close);\n this.content.append(panel);\n this.dialog.classList.remove(\"is-frame\");\n close.focus({ preventScroll: true });\n }\n\n private showLoading(): void {\n this.content.replaceChildren();\n const panel = element(\"div\", \"panel\");\n const spinner = element(\"span\", \"spinner\");\n spinner.setAttribute(\"aria-hidden\", \"true\");\n const label = element(\"p\", \"loading\");\n label.textContent = this.options.labels.loading;\n panel.append(spinner, label);\n this.content.append(panel);\n }\n\n private handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n this.onDismiss();\n }\n };\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n document.removeEventListener(\"keydown\", this.handleKeyDown, true);\n document.body.style.overflow = this.previousOverflow;\n this.host.remove();\n if (this.previousFocus instanceof HTMLElement && this.previousFocus.isConnected) {\n try {\n this.previousFocus.focus({ preventScroll: true });\n } catch {\n // ignore\n }\n }\n this.onLoad = null;\n this.frame = null;\n }\n}\n","import type { CheckoutView } from \"./view\";\n\nexport interface CheckoutWindowOptions {\n title: string;\n labels: {\n loading: string;\n errorTitle: string;\n close: string;\n };\n dir: \"rtl\" | \"ltr\";\n lang: string;\n onDismiss: () => void;\n}\n\nconst WINDOW_NAME = \"esaalat-checkout\";\nconst WINDOW_WIDTH = 480;\nconst WINDOW_HEIGHT = 800;\nconst CLOSE_POLL_MS = 400;\n\nconst DOC_CSS = `\n * { box-sizing: border-box; }\n html, body { height: 100%; }\n body {\n margin: 0;\n display: grid;\n place-items: center;\n padding: 24px;\n background: #f3f0e8;\n color: #0b0b0b;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n }\n .panel {\n display: grid;\n justify-items: center;\n gap: 14px;\n max-width: 34ch;\n text-align: center;\n }\n .error-icon {\n width: 54px;\n height: 54px;\n border-radius: 50%;\n display: grid;\n place-items: center;\n background: #fef1ef;\n border: 1px solid #f5cfca;\n color: #b42318;\n font-size: 24px;\n font-weight: 800;\n }\n .error-title { margin: 0; font-size: 17px; line-height: 1.4; }\n .error-message { margin: 0; font-size: 13px; line-height: 1.7; color: #716f67; }\n .error-close {\n margin-top: 4px;\n min-height: 42px;\n padding: 9px 22px;\n border: 1px solid #ded7c8;\n border-radius: 11px;\n background: transparent;\n color: #0b0b0b;\n font: inherit;\n font-size: 13px;\n font-weight: 700;\n cursor: pointer;\n }\n .error-close:hover { background: #e9e4d8; }\n @media (prefers-color-scheme: dark) {\n body { background: #141310; color: #f6f2e8; }\n .error-message { color: #aaa59a; }\n .error-icon { background: #2b1b19; border-color: #4b2c28; color: #f18d83; }\n .error-close { border-color: #343028; color: #f6f2e8; }\n .error-close:hover { background: #2b2721; }\n }\n`;\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\n/** A centered popup, sized like the checkout card it replaces. */\nfunction windowFeatures(): string {\n const screenWidth = window.screen?.availWidth ?? WINDOW_WIDTH;\n const screenHeight = window.screen?.availHeight ?? WINDOW_HEIGHT;\n const width = Math.min(WINDOW_WIDTH, Math.max(320, screenWidth - 40));\n const height = Math.min(WINDOW_HEIGHT, Math.max(480, screenHeight - 40));\n const baseX = typeof window.screenX === \"number\" ? window.screenX : 0;\n const baseY = typeof window.screenY === \"number\" ? window.screenY : 0;\n const outerWidth = window.outerWidth || width;\n const outerHeight = window.outerHeight || height;\n const left = Math.max(0, Math.round(baseX + (outerWidth - width) / 2));\n const top = Math.max(0, Math.round(baseY + (outerHeight - height) / 2));\n\n return [\n \"popup=yes\",\n `width=${width}`,\n `height=${height}`,\n `left=${left}`,\n `top=${top}`,\n \"resizable=yes\",\n \"scrollbars=yes\",\n ].join(\",\");\n}\n\nfunction documentHtml(\n title: string,\n dir: \"rtl\" | \"ltr\",\n lang: string,\n body: string\n): string {\n return [\n \"<!doctype html>\",\n `<html dir=\"${dir}\" lang=\"${lang}\">`,\n \"<head>\",\n '<meta charset=\"utf-8\" />',\n '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />',\n '<meta name=\"robots\" content=\"noindex\" />',\n `<title>${escapeHtml(title)}</title>`,\n `<style>${DOC_CSS}</style>`,\n \"</head>\",\n `<body>${body}</body>`,\n \"</html>\",\n ].join(\"\");\n}\n\n/**\n * Opens the hosted checkout in its own browser window.\n *\n * The window has to be requested synchronously from the buyer's click, before\n * the session request, or every popup blocker swallows it — so the constructor\n * opens a blank window with a \"preparing checkout\" page and `load()` navigates\n * it once the session exists.\n *\n * The merchant page keeps talking to the portal with `postMessage`: the window\n * handle stays valid across the navigation, and the portal answers the opener\n * (see `createEmbeddedBridge`).\n */\nexport class CheckoutWindow implements CheckoutView {\n private readonly win: Window;\n private readonly onDismiss: () => void;\n private readonly dir: \"rtl\" | \"ltr\";\n private readonly lang: string;\n private readonly title: string;\n private readonly labels: CheckoutWindowOptions[\"labels\"];\n private pollId: number | null = null;\n private navigated = false;\n private destroyed = false;\n\n onLoad: (() => void) | null = null;\n\n constructor(options: CheckoutWindowOptions) {\n const opened = window.open(\"\", WINDOW_NAME, windowFeatures());\n if (!opened) {\n throw new Error(\"The browser blocked the checkout window.\");\n }\n\n this.win = opened;\n this.onDismiss = options.onDismiss;\n this.title = options.title;\n this.labels = options.labels;\n this.dir = options.dir;\n this.lang = options.lang;\n\n this.pollId = window.setInterval(() => this.checkClosed(), CLOSE_POLL_MS);\n\n try {\n this.win.focus();\n } catch {\n // focus is best-effort in embedded browsers\n }\n }\n\n get contentWindow(): Window | null {\n return this.win;\n }\n\n open(): void {\n try {\n this.win.focus();\n } catch {\n // focus is best-effort\n }\n }\n\n load(url: string): void {\n if (this.destroyed) return;\n this.navigated = true;\n try {\n // `replace` keeps the empty window out of the buyer's back history.\n this.win.location.replace(url);\n } catch {\n if (this.win.closed) {\n this.dismiss();\n return;\n }\n // Some embedded browsers refuse one navigation call but accept another.\n try {\n this.win.location.href = url;\n } catch {\n // The portal never loaded; the close poll will notice if it is gone.\n }\n }\n this.onLoad?.();\n }\n\n showError(message: string): void {\n // After the navigation the portal owns that document; nothing safe to paint.\n if (this.destroyed || this.navigated) return;\n\n this.renderError(\n documentHtml(\n this.title,\n this.dir,\n this.lang,\n `<div class=\"panel\">` +\n `<span class=\"error-icon\" aria-hidden=\"true\">!</span>` +\n `<h2 class=\"error-title\">${escapeHtml(this.labels.errorTitle)}</h2>` +\n `<p class=\"error-message\">${escapeHtml(message)}</p>` +\n `<button class=\"error-close\" type=\"button\">${escapeHtml(this.labels.close)}</button>` +\n `</div>`\n )\n );\n\n try {\n const close = this.win.document.querySelector(\".error-close\");\n close?.addEventListener(\"click\", () => this.onDismiss());\n } catch {\n // The window went away before the close button could be wired.\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.stopPolling();\n this.onLoad = null;\n try {\n this.win.close();\n } catch {\n // Already closed by the buyer.\n }\n }\n\n /**\n * Best-effort: the placeholder document is cosmetic. A refused write must\n * never cancel the checkout — the navigation below still has to happen.\n */\n private renderError(html: string): void {\n try {\n const doc = this.win.document;\n doc.open();\n doc.write(html);\n doc.close();\n } catch {\n // Browser refused to let us paint into the blank window.\n }\n }\n\n private checkClosed(): void {\n if (this.destroyed) {\n this.stopPolling();\n return;\n }\n if (this.win.closed) this.dismiss();\n }\n\n private dismiss(): void {\n if (this.destroyed) return;\n this.stopPolling();\n this.onDismiss();\n }\n\n private stopPolling(): void {\n if (this.pollId !== null) {\n window.clearInterval(this.pollId);\n this.pollId = null;\n }\n }\n}\n","import { EsaalatCheckoutError } from \"./errors\";\nimport { CheckoutModal } from \"./modal\";\nimport type {\n CheckoutBeforeCreateOrderHandler,\n CheckoutCreatePayload,\n CheckoutItem,\n CheckoutLocale,\n CheckoutOpenOptions,\n CheckoutPresentation,\n CheckoutResult,\n CheckoutResultReason,\n CheckoutResultStatus,\n CheckoutSession,\n EsaalatCheckoutOptions,\n} from \"./types\";\nimport type { CheckoutView } from \"./view\";\nimport { CheckoutWindow } from \"./window\";\n\nconst DEFAULT_API_BASE = \"https://api.esaalat.com/api/v1\";\nconst DEFAULT_PORTAL_BASE = \"https://pay.esaalat.com\";\nconst SDK_VERSION = \"0.1.0\";\nconst REQUEST_TIMEOUT_MS = 20_000;\nconst INIT_RETRY_MS = 300;\n// A browser window needs longer than an iframe: the init message races the\n// navigation, so keep knocking until the portal answers `ready`.\nconst INIT_ATTEMPTS = 100;\nconst VERIFIED_CLOSE_MS = 1_800;\nconst ERROR_CLOSE_MS = 6_000;\n\nconst RESULT_STATUSES: CheckoutResultStatus[] = [\n \"VERIFIED\",\n \"WRONG_AMOUNT\",\n \"EXPIRED\",\n \"CANCELLED\",\n \"FAILED\",\n];\n\nconst RESULT_REASONS: CheckoutResultReason[] = [\n \"dismissed\",\n \"destroyed\",\n \"intent_cancelled\",\n \"session_expired\",\n \"session_not_found\",\n \"network_error\",\n];\n\ninterface ActiveCheckout {\n token: string | null;\n locale: CheckoutLocale;\n controller: AbortController;\n view: CheckoutView;\n settled: boolean;\n resolve: (result: CheckoutResult) => void;\n reject: (error: Error) => void;\n onResult?: (result: CheckoutResult) => void;\n}\n\ninterface PortalMessage {\n source?: unknown;\n type?: unknown;\n sessionToken?: unknown;\n payload?: unknown;\n}\n\ninterface PortalResultPayload {\n status?: unknown;\n reason?: unknown;\n intentCode?: unknown;\n amount?: unknown;\n paidAmount?: unknown;\n currency?: unknown;\n externalOrderId?: unknown;\n merchantName?: unknown;\n}\n\nfunction normalizeBase(value: string, fallback: string): string {\n const raw = value.trim() || fallback;\n let url: URL;\n try {\n const base =\n typeof window !== \"undefined\" ? window.location?.href : undefined;\n url = new URL(raw, base);\n } catch {\n throw new EsaalatCheckoutError(\n `Invalid URL: ${raw}`,\n \"configuration\"\n );\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new EsaalatCheckoutError(\n `Unsupported URL protocol: ${url.protocol}`,\n \"configuration\"\n );\n }\n return url.toString().replace(/\\/+$/, \"\");\n}\n\nfunction requestId(): string {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n // UUID v4 fallback for older embedded browsers.\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (char) => {\n const random = (Math.random() * 16) | 0;\n const value = char === \"x\" ? random : (random & 0x3) | 0x8;\n return value.toString(16);\n });\n}\n\nfunction stringOr(value: unknown, fallback = \"\"): string {\n return typeof value === \"string\" ? value : fallback;\n}\n\nfunction nullOrString(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction errorDetail(body: unknown): string | null {\n if (!body || typeof body !== \"object\") return null;\n const record = body as Record<string, unknown>;\n if (typeof record.detail === \"string\") return record.detail;\n if (Array.isArray(record.errors)) {\n for (const error of record.errors) {\n if (error && typeof error === \"object\") {\n const detail = (error as Record<string, unknown>).detail;\n if (typeof detail === \"string\") return detail;\n }\n }\n }\n for (const value of Object.values(record)) {\n if (typeof value === \"string\") return value;\n if (Array.isArray(value) && typeof value[0] === \"string\") return value[0];\n }\n return null;\n}\n\nfunction isCheckoutSession(value: unknown): value is CheckoutSession {\n if (!value || typeof value !== \"object\") return false;\n const record = value as Record<string, unknown>;\n return (\n typeof record.session_token === \"string\" &&\n typeof record.portal_url === \"string\" &&\n typeof record.amount === \"string\" &&\n typeof record.currency === \"string\"\n );\n}\n\nfunction cancelledResult(\n token: string | null,\n reason: \"dismissed\" | \"destroyed\"\n): CheckoutResult {\n return {\n status: \"CANCELLED\",\n reason,\n sessionToken: token ?? \"\",\n intentCode: null,\n amount: \"0.00\",\n paidAmount: null,\n currency: \"YER\",\n externalOrderId: \"\",\n merchantName: \"\",\n };\n}\n\n/**\n * Framework-agnostic Esaalat checkout client.\n *\n * It creates a checkout session with the merchant's publishable key, opens the\n * Esaalat-hosted portal in its own browser window (or an in-page modal when\n * asked, or when the browser blocks the window), and resolves `open()` with a\n * terminal result. The publishable key is public by design; keep the client\n * secret and any order confirmation on the server.\n */\nexport class EsaalatCheckout {\n private readonly publishableKey: string;\n private readonly apiBaseUrl: string;\n private readonly portalBaseUrl: string;\n private readonly zIndex: number;\n private readonly presentation: CheckoutPresentation;\n private readonly locale: CheckoutLocale;\n private readonly fetchImpl: typeof fetch | null;\n private readonly defaultOnResult?: (result: CheckoutResult) => void;\n private readonly defaultOnError?: (error: Error) => void;\n\n private active: ActiveCheckout | null = null;\n private view: CheckoutView | null = null;\n private portalOrigin: string | null = null;\n private sessionToken: string | null = null;\n private initTimer: number | null = null;\n private verifiedTimer: number | null = null;\n private errorTimer: number | null = null;\n\n constructor(options: EsaalatCheckoutOptions) {\n // The key is only needed to create a session in the browser. A merchant\n // that opens a server-created session passes its token instead, so an\n // empty key is allowed here and refused by `open()` only on the create\n // path.\n const key =\n typeof options?.publishableKey === \"string\"\n ? options.publishableKey.trim()\n : \"\";\n\n this.publishableKey = key;\n this.locale =\n options.locale === \"en\" || options.locale === \"ar\" ? options.locale : \"ar\";\n this.apiBaseUrl = normalizeBase(options.apiBaseUrl ?? \"\", DEFAULT_API_BASE);\n this.portalBaseUrl = normalizeBase(\n options.portalBaseUrl ?? \"\",\n DEFAULT_PORTAL_BASE\n );\n this.zIndex =\n typeof options.zIndex === \"number\" && Number.isFinite(options.zIndex)\n ? options.zIndex\n : 2_147_483_000;\n this.presentation =\n options.presentation === \"modal\" ? \"modal\" : \"window\";\n\n const fetchFromOptions = options.fetch;\n const globalFetch =\n typeof fetch === \"function\" ? fetch.bind(globalThis) : null;\n this.fetchImpl = fetchFromOptions ?? globalFetch;\n this.defaultOnResult = options.onResult;\n this.defaultOnError = options.onError;\n }\n\n /** True while a checkout window or modal is on screen. */\n get isOpen(): boolean {\n return this.view !== null;\n }\n\n /**\n * Open the hosted checkout and resolve with its terminal result.\n *\n * A second call while a checkout is open rejects; close the first one with\n * `close()` or wait for its result.\n */\n async open(options: CheckoutOpenOptions = {}): Promise<CheckoutResult> {\n if (this.active || this.view) {\n throw new EsaalatCheckoutError(\n \"A checkout is already open. Close it before starting another.\",\n \"configuration\"\n );\n }\n if (!this.fetchImpl) {\n throw new EsaalatCheckoutError(\n \"This browser does not support fetch. Use the SDK on a modern browser.\",\n \"configuration\"\n );\n }\n\n const locale =\n options.locale === \"en\" || options.locale === \"ar\"\n ? options.locale\n : this.locale;\n const items = options.items ?? [];\n const existingToken = options.sessionToken?.trim() || null;\n const hasAmount =\n options.amount !== undefined &&\n options.amount !== null &&\n String(options.amount).trim() !== \"\";\n if (!existingToken && !this.publishableKey) {\n throw new EsaalatCheckoutError(\n \"A publishable key is required to create a session. Pass one, or open a server-created `sessionToken`.\",\n \"configuration\"\n );\n }\n if (!existingToken && !hasAmount && items.length === 0) {\n throw new EsaalatCheckoutError(\n \"Provide an amount, items, or a server-created session token.\",\n \"configuration\"\n );\n }\n if (!existingToken && items.length > 0) {\n for (const item of items) {\n if (!item.name || item.price === undefined || item.price === null) {\n throw new EsaalatCheckoutError(\n \"Every item needs a name and a price.\",\n \"configuration\"\n );\n }\n }\n }\n\n const labels =\n locale === \"ar\"\n ? {\n close: \"إغلاق\",\n loading: \"جارٍ تجهيز الدفع الآمن…\",\n errorTitle: \"تعذّر بدء الدفع\",\n }\n : {\n close: \"Close\",\n loading: \"Preparing secure checkout…\",\n errorTitle: \"Couldn't start the checkout\",\n };\n\n const presentation: CheckoutPresentation =\n options.presentation === \"window\" || options.presentation === \"modal\"\n ? options.presentation\n : this.presentation;\n\n // The view is created before the first `await`: a browser window has to be\n // requested inside the buyer's click, or popup blockers discard it.\n let view: CheckoutView;\n try {\n view = this.createView(presentation, labels, locale);\n view.open();\n } catch (error) {\n throw new EsaalatCheckoutError(\n \"The checkout could not be opened.\",\n \"unavailable\",\n { cause: error }\n );\n }\n\n const controller = new AbortController();\n let resolvePromise!: (result: CheckoutResult) => void;\n let rejectPromise!: (error: Error) => void;\n const promise = new Promise<CheckoutResult>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n });\n\n const onResult = options.onResult ?? this.defaultOnResult;\n const onError = options.onError ?? this.defaultOnError;\n\n const active: ActiveCheckout = {\n token: null,\n locale,\n controller,\n view,\n settled: false,\n resolve: resolvePromise,\n reject: rejectPromise,\n onResult,\n };\n this.active = active;\n this.view = view;\n this.sessionToken = null;\n this.portalOrigin = null;\n\n view.onLoad = () => this.startInitRetry();\n\n let portalUrl: string;\n try {\n if (existingToken) {\n active.token = existingToken;\n this.sessionToken = existingToken;\n portalUrl = this.buildPortalUrl(\n existingToken,\n options.portalUrl ?? \"\",\n locale\n );\n } else {\n const session = await this.createSession(\n options,\n locale,\n controller.signal\n );\n // The buyer closed the checkout while the session was being created.\n if (active.settled) return promise;\n active.token = session.session_token;\n this.sessionToken = session.session_token;\n portalUrl = this.buildPortalUrl(\n session.session_token,\n session.portal_url,\n locale\n );\n }\n this.portalOrigin = new URL(portalUrl).origin;\n } catch (error) {\n if (active.settled) return promise;\n const wrapped =\n error instanceof EsaalatCheckoutError\n ? error\n : new EsaalatCheckoutError(\n \"Esaalat returned an invalid checkout URL.\",\n \"session\",\n { cause: error }\n );\n active.settled = true;\n this.active = null;\n this.removeMessageListener();\n try {\n onError?.(wrapped);\n } catch {\n // A merchant callback must not prevent the promise from settling.\n }\n active.reject(wrapped);\n view.showError(wrapped.message);\n this.errorTimer = window.setTimeout(() => {\n if (this.view === view) this.teardown();\n }, ERROR_CLOSE_MS);\n return promise;\n }\n\n window.addEventListener(\"message\", this.handleMessage);\n view.load(portalUrl);\n return promise;\n }\n\n /** Close the checkout. An in-flight `open()` resolves with CANCELLED. */\n close(): void {\n if (this.active) {\n this.dismiss();\n return;\n }\n this.teardown();\n }\n\n /** Remove the checkout view and any listeners without resolving a result. */\n destroy(): void {\n if (this.active && !this.active.settled) {\n this.finish(cancelledResult(this.sessionToken, \"destroyed\"));\n return;\n }\n this.teardown();\n }\n\n private createView(\n presentation: CheckoutPresentation,\n labels: { close: string; loading: string; errorTitle: string },\n locale: CheckoutLocale\n ): CheckoutView {\n const title =\n locale === \"ar\" ? \"إيصالات — دفع آمن\" : \"Esaalat — Secure checkout\";\n const onDismiss = () => this.dismiss();\n\n if (presentation === \"window\") {\n try {\n return new CheckoutWindow({\n title,\n labels,\n dir: locale === \"ar\" ? \"rtl\" : \"ltr\",\n lang: locale,\n onDismiss,\n });\n } catch {\n // The popup was blocked (or there is no window): the modal is the\n // always-available fallback, so the buyer still gets to pay.\n }\n }\n\n return new CheckoutModal({\n zIndex: this.zIndex,\n title,\n labels,\n onDismiss,\n });\n }\n\n private buildPortalUrl(\n sessionToken: string,\n rawPortalUrl: string,\n locale: CheckoutLocale\n ): string {\n const raw =\n rawPortalUrl.trim() ||\n `${this.portalBaseUrl}/checkout/${encodeURIComponent(sessionToken)}`;\n const url = new URL(raw);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new Error(\"Unsupported portal protocol\");\n }\n url.searchParams.set(\"lang\", locale);\n return url.toString();\n }\n\n private async createSession(\n options: CheckoutOpenOptions,\n locale: CheckoutLocale,\n outerSignal: AbortSignal\n ): Promise<CheckoutSession> {\n if (!this.fetchImpl) {\n throw new EsaalatCheckoutError(\"fetch is unavailable\", \"configuration\");\n }\n\n let payload: CheckoutCreatePayload = {};\n if (options.amount !== undefined && options.amount !== null) {\n payload.amount = String(options.amount);\n }\n if (options.items?.length) {\n payload.items = options.items.map((item: CheckoutItem) => ({\n name: item.name,\n ...(item.description ? { description: item.description } : {}),\n price: String(item.price),\n quantity: item.quantity ?? 1,\n }));\n }\n if (options.currency) payload.currency = options.currency;\n if (options.externalOrderId) {\n payload.external_order_id = options.externalOrderId;\n }\n if (options.notes) payload.notes = options.notes;\n if (options.wallet) payload.wallet = options.wallet;\n\n // The merchant's last word on what is sent. Whatever this throws becomes\n // the checkout's own error, so a veto reaches `open()` as `configuration`\n // with the merchant's message instead of being swallowed.\n const beforeCreate: CheckoutBeforeCreateOrderHandler | undefined =\n options.onBeforeCreateOrder;\n if (beforeCreate) {\n let updated: CheckoutCreatePayload | void;\n try {\n updated = await beforeCreate(payload);\n } catch (error) {\n throw new EsaalatCheckoutError(\n error instanceof Error && error.message\n ? error.message\n : locale === \"ar\"\n ? \"أُلغي الدفع.\"\n : \"The checkout was cancelled.\",\n \"configuration\",\n { cause: error }\n );\n }\n if (updated && typeof updated === \"object\") payload = updated;\n }\n\n const controller = new AbortController();\n let timedOut = false;\n const timeout = window.setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, REQUEST_TIMEOUT_MS);\n const abortOuter = () => controller.abort();\n outerSignal.addEventListener(\"abort\", abortOuter);\n\n try {\n const response = await this.fetchImpl(\n `${this.apiBaseUrl}/checkout/sdk/sessions/`,\n {\n method: \"POST\",\n credentials: \"omit\",\n cache: \"no-store\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n \"ESAALAT-PUBLISHABLE-KEY\": this.publishableKey,\n \"ESAALAT-IDEMPOTENCY-KEY\":\n options.idempotencyKey?.trim() || requestId(),\n \"ESAALAT-SDK-VERSION\": SDK_VERSION,\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n }\n );\n\n const session: unknown = await response.json().catch(() => null);\n if (!response.ok) {\n throw new EsaalatCheckoutError(\n errorDetail(session) ||\n (locale === \"ar\"\n ? \"تعذّر إنشاء جلسة الدفع.\"\n : \"Couldn't create the checkout session.\"),\n \"api\",\n { status: response.status, details: session }\n );\n }\n if (!isCheckoutSession(session)) {\n throw new EsaalatCheckoutError(\n \"Esaalat returned an invalid checkout session.\",\n \"session\",\n { details: session }\n );\n }\n\n // The session exists; a broken listener must not kill the payment.\n try {\n options.onOrderCreated?.(session);\n } catch {\n // Ignored on purpose.\n }\n\n return session;\n } catch (error) {\n if (error instanceof EsaalatCheckoutError) throw error;\n if (timedOut) {\n throw new EsaalatCheckoutError(\n locale === \"ar\"\n ? \"انتهت مهلة الاتصال بإيصالات. حاول مرة أخرى.\"\n : \"The connection to Esaalat timed out. Please try again.\",\n \"network\",\n { cause: error }\n );\n }\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw error;\n }\n throw new EsaalatCheckoutError(\n locale === \"ar\"\n ? \"تعذّر الاتصال بإيصالات. تحقق من اتصالك وحاول مرة أخرى.\"\n : \"Couldn't reach Esaalat. Check your connection and try again.\",\n \"network\",\n { cause: error }\n );\n } finally {\n window.clearTimeout(timeout);\n outerSignal.removeEventListener(\"abort\", abortOuter);\n }\n }\n\n private startInitRetry(): void {\n this.clearInitTimer();\n let attempts = 0;\n\n const tick = () => {\n if (!this.view || !this.portalOrigin || !this.sessionToken) return;\n this.postInit();\n attempts += 1;\n if (attempts < INIT_ATTEMPTS) {\n this.initTimer = window.setTimeout(tick, INIT_RETRY_MS);\n } else {\n this.initTimer = null;\n }\n };\n\n tick();\n }\n\n private postInit(): void {\n const target = this.view?.contentWindow;\n if (!target || !this.portalOrigin || !this.sessionToken) return;\n const message = {\n source: \"esaalat-checkout-sdk\",\n version: 1,\n type: \"init\",\n sessionToken: this.sessionToken,\n parentOrigin: window.location.origin,\n locale: this.active?.locale ?? this.locale,\n };\n try {\n target.postMessage(message, this.portalOrigin);\n } catch {\n // The iframe may have been torn down between the check and the post.\n }\n }\n\n private clearInitTimer(): void {\n if (this.initTimer !== null) {\n window.clearTimeout(this.initTimer);\n this.initTimer = null;\n }\n }\n\n private handleMessage = (event: MessageEvent): void => {\n if (!this.view || !this.portalOrigin) return;\n if (event.source !== this.view.contentWindow) return;\n if (event.origin !== this.portalOrigin) return;\n\n const data = event.data as PortalMessage | null;\n if (!data || typeof data !== \"object\") return;\n if (data.source !== \"esaalat-checkout\") return;\n if (data.sessionToken !== this.sessionToken) return;\n\n if (data.type === \"ready\") {\n this.clearInitTimer();\n return;\n }\n\n if (data.type === \"close\") {\n this.dismiss();\n return;\n }\n\n if (data.type === \"result\") {\n const result = this.parseResult(data.payload);\n if (result) this.finish(result);\n }\n };\n\n private parseResult(payload: unknown): CheckoutResult | null {\n if (!payload || typeof payload !== \"object\") return null;\n const value = payload as PortalResultPayload;\n if (\n typeof value.status !== \"string\" ||\n !RESULT_STATUSES.includes(value.status as CheckoutResultStatus)\n ) {\n return null;\n }\n\n const reason =\n typeof value.reason === \"string\" &&\n RESULT_REASONS.includes(value.reason as CheckoutResultReason)\n ? (value.reason as CheckoutResultReason)\n : undefined;\n\n return {\n status: value.status as CheckoutResultStatus,\n ...(reason ? { reason } : {}),\n sessionToken: this.sessionToken ?? \"\",\n intentCode: nullOrString(value.intentCode),\n amount: stringOr(value.amount, \"0.00\"),\n paidAmount: nullOrString(value.paidAmount),\n currency: stringOr(value.currency, \"YER\"),\n externalOrderId: stringOr(value.externalOrderId),\n merchantName: stringOr(value.merchantName),\n };\n }\n\n private finish(result: CheckoutResult): void {\n const active = this.active;\n if (!active || active.settled) return;\n\n active.settled = true;\n this.active = null;\n this.clearInitTimer();\n active.controller.abort();\n try {\n active.onResult?.(result);\n } catch {\n // A merchant callback must not prevent the promise from settling.\n }\n active.resolve(result);\n\n if (result.reason === \"dismissed\" || result.reason === \"destroyed\") {\n this.teardown();\n return;\n }\n\n if (result.status === \"VERIFIED\") {\n this.verifiedTimer = window.setTimeout(() => this.teardown(), VERIFIED_CLOSE_MS);\n }\n // Other terminal states stay visible until the buyer closes them, so the\n // reason (wrong amount, expiry, cancellation) is not flashed away.\n }\n\n private dismiss(): void {\n if (this.active && !this.active.settled) {\n this.finish(cancelledResult(this.sessionToken, \"dismissed\"));\n return;\n }\n this.teardown();\n }\n\n private removeMessageListener(): void {\n window.removeEventListener(\"message\", this.handleMessage);\n }\n\n private clearTimers(): void {\n this.clearInitTimer();\n if (this.verifiedTimer !== null) {\n window.clearTimeout(this.verifiedTimer);\n this.verifiedTimer = null;\n }\n if (this.errorTimer !== null) {\n window.clearTimeout(this.errorTimer);\n this.errorTimer = null;\n }\n }\n\n private teardown(): void {\n this.clearTimers();\n this.removeMessageListener();\n if (this.view) {\n this.view.destroy();\n this.view = null;\n }\n this.portalOrigin = null;\n this.sessionToken = null;\n this.active = null;\n }\n}\n","import { EsaalatCheckout } from \"./client\";\nimport { EsaalatCheckoutError } from \"./errors\";\nimport type {\n CheckoutBeforeCreateOrderHandler,\n CheckoutItem,\n CheckoutLocale,\n CheckoutOpenOptions,\n CheckoutPresentation,\n CheckoutResult,\n CheckoutResultStatus,\n CheckoutSession,\n} from \"./types\";\n\n/**\n * A \"Pay with Esaalat\" button that any framework can render.\n *\n * It is a custom element, not a React/Vue/Angular component, because the\n * checkout is one behaviour that should not be reimplemented per framework:\n * the same tag and the same attributes work in plain HTML, in a Vue template\n * (`@esaalat-verified`), in an Angular template (`(esaalat-verified)` with\n * `CUSTOM_ELEMENTS_SCHEMA`) and — through `esaalat-react`, which only sets\n * properties and listeners — in JSX.\n *\n * The element is a thin shell over `EsaalatCheckout`: a click calls `open()`\n * with the attributes as options, and the terminal result is routed to ONE\n * named callback per outcome (see `OUTCOMES`). Nothing here re-implements the\n * portal, the session API or the result contract.\n *\n * ```html\n * <esaalat-checkout-button\n * publishable-key=\"pk_live_...\"\n * amount=\"5000.00\"\n * external-order-id=\"order-123\"\n * ></esaalat-checkout-button>\n * <script>\n * const button = document.querySelector(\"esaalat-checkout-button\");\n * button.onVerified = (result) => console.log(result.intentCode);\n * button.onCancelled = () => console.log(\"not this time\");\n * </script>\n * ```\n */\n\n/** The tag this element is registered under. */\nexport const ESAALAT_CHECKOUT_BUTTON_TAG = \"esaalat-checkout-button\";\n\n/** Label shown when the merchant passes neither `label` nor child text. */\nconst DEFAULT_LABELS: Record<CheckoutLocale, string> = {\n ar: \"ادفع الآن\",\n en: \"Pay now\",\n};\n\ntype HandlerName =\n | \"onVerified\"\n | \"onCancelled\"\n | \"onWrongAmount\"\n | \"onExpired\"\n | \"onFailed\";\n\n/**\n * One callback per terminal status: the buyer's outcome picks exactly one row,\n * so a merchant never has to switch on `result.status` to find the interesting\n * case. `FAILED` is a result (the portal could not load a valid session), not a\n * thrown error — `onError` stays reserved for `open()` rejecting.\n */\nconst OUTCOMES: Record<\n CheckoutResultStatus,\n { handler: HandlerName; event: string }\n> = {\n VERIFIED: { handler: \"onVerified\", event: \"esaalat-verified\" },\n CANCELLED: { handler: \"onCancelled\", event: \"esaalat-cancelled\" },\n WRONG_AMOUNT: { handler: \"onWrongAmount\", event: \"esaalat-wrong-amount\" },\n EXPIRED: { handler: \"onExpired\", event: \"esaalat-expired\" },\n FAILED: { handler: \"onFailed\", event: \"esaalat-failed\" },\n};\n\n/** Names of the DOM events, exported for `addEventListener` users. */\nexport const ESAALAT_CHECKOUT_EVENTS = {\n verified: \"esaalat-verified\",\n cancelled: \"esaalat-cancelled\",\n wrongAmount: \"esaalat-wrong-amount\",\n expired: \"esaalat-expired\",\n failed: \"esaalat-failed\",\n error: \"esaalat-error\",\n} as const;\n\n/** How often the button re-checks whether its checkout has been closed. */\nconst WATCH_INTERVAL_MS = 300;\n\nfunction asError(error: unknown): Error {\n if (error instanceof Error) return error;\n return new EsaalatCheckoutError(String(error) || \"The checkout failed.\", \"unavailable\");\n}\n\n/**\n * `HTMLElement` where it exists, an empty base where it does not.\n *\n * A custom element class cannot be declared against a global that Node does\n * not have, and this module has to be importable during server rendering:\n * Next renders client components on the server, so a static import of\n * `esaalat-react` would otherwise throw `HTMLElement is not defined` before\n * the browser ever gets the module. Nothing on the server instantiates the\n * class, so the empty base is never used — `registerEsaalatCheckoutButton`\n * stays a no-op without `customElements`.\n */\nconst HTMLElementBase: typeof HTMLElement =\n typeof HTMLElement === \"undefined\"\n ? (class {} as unknown as typeof HTMLElement)\n : HTMLElement;\n\nexport class EsaalatCheckoutButtonElement extends HTMLElementBase {\n static get observedAttributes(): string[] {\n return [\n \"publishable-key\",\n \"amount\",\n \"currency\",\n \"external-order-id\",\n \"notes\",\n \"wallet\",\n \"locale\",\n \"presentation\",\n \"session-token\",\n \"portal-url\",\n \"label\",\n \"disabled\",\n \"items\",\n ];\n }\n\n /** Called with the result when the wallet alert verified the payment. */\n onVerified?: (result: CheckoutResult) => void;\n /** Called when the buyer dismissed the checkout, or the intent was cancelled. */\n onCancelled?: (result: CheckoutResult) => void;\n /** Called when a payment matched but for a different amount. */\n onWrongAmount?: (result: CheckoutResult) => void;\n /** Called when the buyer ran out of time. */\n onExpired?: (result: CheckoutResult) => void;\n /** Called when the portal could not load a valid session. */\n onFailed?: (result: CheckoutResult) => void;\n /** Called when `open()` rejects (configuration, network, API or unavailable). */\n onError?: (error: Error) => void;\n\n /**\n * Called just before this button creates the session in the browser, with\n * the body about to be sent. Return an object to add or override fields\n * (`external_order_id`, `notes`, anything your API accepts); throwing\n * cancels the checkout and reports the message via `onError`.\n */\n onBeforeCreateOrder?: CheckoutBeforeCreateOrderHandler;\n\n /**\n * Called with the created session (token, intent, expiry...) when this\n * button created it in the browser. Not called when a `session-token`\n * attribute is set, because that session was made on your server.\n */\n onOrderCreated?: (session: CheckoutSession) => void;\n\n /**\n * Order lines as data. The `items` attribute carries the same as JSON, for\n * HTML templates that have no way to set a property.\n */\n items: CheckoutItem[] | null = null;\n\n private client: EsaalatCheckout | null = null;\n private clientKey: string | null = null;\n private button: HTMLButtonElement | null = null;\n private busy = false;\n private watchTimer: ReturnType<typeof setInterval> | null = null;\n /** Text written between the tags, captured before the button is injected. */\n private slotLabel: string | null = null;\n\n connectedCallback(): void {\n this.render();\n }\n\n disconnectedCallback(): void {\n // The checkout itself lives on `document.body`, so a removed button must\n // not cancel a payment in progress. Only the state watcher goes away.\n this.stopWatch();\n }\n\n attributeChangedCallback(\n name: string,\n previous: string | null,\n value: string | null\n ): void {\n if (previous === value) return;\n\n if (name === \"publishable-key\") {\n // A different key means a different client; the next click builds it.\n this.client = null;\n this.clientKey = null;\n return;\n }\n if (name === \"label\" || name === \"locale\") {\n this.applyLabel();\n return;\n }\n if (name === \"disabled\") {\n this.syncBusy();\n }\n }\n\n /** Open the checkout, exactly as a click does (for programmatic use). */\n async open(): Promise<void> {\n await this.start();\n }\n\n private handleClick = (): void => {\n // Not awaited: the click task must keep running synchronously so the\n // browser-window presentation is still inside the buyer's gesture.\n void this.start();\n };\n\n private async start(): Promise<void> {\n if (this.busy || this.isCheckoutOpen()) return;\n\n const key = (this.getAttribute(\"publishable-key\") ?? \"\").trim();\n // A `session-token` already names the checkout; the key only creates one.\n if (!key && !this.attribute(\"session-token\")) {\n this.reportError(\n new EsaalatCheckoutError(\"A publishable key is required.\", \"configuration\")\n );\n return;\n }\n\n this.setBusy(true);\n this.watch();\n\n try {\n const items = this.readItems();\n const client = this.ensureClient(key);\n const result = await client.open(this.openOptions(items));\n this.handleResult(result);\n } catch (error) {\n this.reportError(asError(error));\n } finally {\n this.setBusy(false);\n }\n }\n\n private ensureClient(key: string): EsaalatCheckout {\n if (this.client && this.clientKey === key) return this.client;\n // Replacing the client only happens when the key changes. It has no open\n // checkout to lose: `start()` refuses to run while one is on screen.\n this.clientKey = key;\n this.client = new EsaalatCheckout({\n publishableKey: key,\n locale: this.locale(),\n });\n return this.client;\n }\n\n private openOptions(items: CheckoutItem[] | null): CheckoutOpenOptions {\n return {\n amount: this.attribute(\"amount\"),\n items: items ?? undefined,\n currency: this.attribute(\"currency\"),\n externalOrderId: this.attribute(\"external-order-id\"),\n notes: this.attribute(\"notes\"),\n wallet: this.attribute(\"wallet\"),\n sessionToken: this.attribute(\"session-token\"),\n portalUrl: this.attribute(\"portal-url\"),\n locale: this.locale(),\n presentation: this.presentation(),\n onBeforeCreateOrder: this.onBeforeCreateOrder,\n onOrderCreated: this.onOrderCreated,\n };\n }\n\n private handleResult(result: CheckoutResult): void {\n const outcome = OUTCOMES[result.status];\n if (!outcome) return;\n\n // The status is the single source of truth: only the matching callback\n // runs, so a merchant can wire all five without guarding each one.\n this.callSafely(this[outcome.handler] as ((r: CheckoutResult) => void) | undefined, result);\n this.dispatchOutcome(outcome.event, result);\n }\n\n private reportError(error: Error): void {\n this.callSafely(this.onError, error);\n this.dispatchOutcome(ESAALAT_CHECKOUT_EVENTS.error, error);\n }\n\n /**\n * DOM events carry the same detail as the callbacks, so templates that bind\n * events instead of properties (`@esaalat-verified`, `(esaalat-verified)`)\n * need no extra JS.\n */\n private dispatchOutcome(name: string, detail: CheckoutResult | Error): void {\n this.dispatchEvent(\n new CustomEvent(name, { detail, bubbles: true, composed: true })\n );\n }\n\n private callSafely<Arg>(handler: ((argument: Arg) => void) | undefined, argument: Arg): void {\n if (!handler) return;\n try {\n handler(argument);\n } catch {\n // A merchant callback must never break the element's own bookkeeping.\n }\n }\n\n private readItems(): CheckoutItem[] | null {\n if (this.items && this.items.length > 0) return this.items;\n\n const raw = this.attribute(\"items\");\n if (!raw) return null;\n try {\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) throw new Error(\"not an array\");\n return parsed as CheckoutItem[];\n } catch {\n throw new EsaalatCheckoutError(\n \"The items attribute must be a JSON array of order lines.\",\n \"configuration\"\n );\n }\n }\n\n private attribute(name: string): string | undefined {\n const value = (this.getAttribute(name) ?? \"\").trim();\n return value || undefined;\n }\n\n private locale(): CheckoutLocale {\n return this.getAttribute(\"locale\") === \"en\" ? \"en\" : \"ar\";\n }\n\n private presentation(): CheckoutPresentation {\n // A component implies in-page, so the modal is the default here even\n // though the imperative client opens a browser window by default.\n return this.getAttribute(\"presentation\") === \"window\" ? \"window\" : \"modal\";\n }\n\n private isCheckoutOpen(): boolean {\n return this.client?.isOpen ?? false;\n }\n\n // -- rendering -----------------------------------------------------------\n\n private render(): void {\n if (!this.button) {\n // Read any \"Pay now\" written between the tags before the button exists,\n // so `<esaalat-checkout-button>Pay</esaalat-checkout-button>` works.\n if (this.slotLabel === null) {\n this.slotLabel = (this.textContent ?? \"\").trim();\n }\n\n const button = this.ownerDocument.createElement(\"button\");\n button.type = \"button\";\n button.className = \"esaalat-checkout-button\";\n button.addEventListener(\"click\", this.handleClick);\n this.replaceChildren(button);\n this.button = button;\n this.applyStyles(button);\n }\n this.applyLabel();\n this.syncBusy();\n }\n\n private applyLabel(): void {\n if (!this.button) return;\n const label =\n this.attribute(\"label\") ??\n (this.slotLabel || undefined) ??\n DEFAULT_LABELS[this.locale()];\n this.button.textContent = label;\n }\n\n /**\n * Defaults live on the inner button and read CSS custom properties, so a\n * merchant themes the control from their own stylesheet without the element\n * shipping a global stylesheet or a shadow root that would trap their CSS.\n */\n private applyStyles(button: HTMLButtonElement): void {\n button.style.appearance = \"none\";\n button.style.border =\n \"1px solid var(--esaalat-button-border, transparent)\";\n button.style.borderRadius = \"var(--esaalat-button-radius, 12px)\";\n button.style.background = \"var(--esaalat-button-background, #1f2a24)\";\n button.style.color = \"var(--esaalat-button-color, #ffffff)\";\n button.style.font = \"inherit\";\n button.style.fontSize = \"var(--esaalat-button-font-size, 15px)\";\n button.style.fontWeight = \"600\";\n button.style.lineHeight = \"1.2\";\n button.style.padding = \"var(--esaalat-button-padding, 14px 22px)\";\n button.style.cursor = \"pointer\";\n button.style.transition = \"opacity 120ms ease-out\";\n }\n\n private setBusy(busy: boolean): void {\n this.busy = busy;\n this.syncBusy();\n }\n\n private syncBusy(): void {\n if (!this.button) return;\n const busy = this.busy || this.isCheckoutOpen();\n // `disabled` always locks the button; otherwise it is locked only while\n // this element is the one driving a checkout.\n const locked = busy || this.hasAttribute(\"disabled\");\n this.button.disabled = locked;\n this.button.setAttribute(\"aria-busy\", busy ? \"true\" : \"false\");\n this.button.style.opacity = this.hasAttribute(\"disabled\") && !busy ? \"0.6\" : \"1\";\n this.button.style.cursor = locked ? \"default\" : \"pointer\";\n }\n\n // -- state watcher -------------------------------------------------------\n\n /**\n * A result resolves `open()`, but the portal stays on screen for a moment\n * (`VERIFIED` auto-closes; every other outcome waits for the buyer to close\n * it). The button has to stay locked until then — a click in that window\n * would only reach \"a checkout is already open\".\n */\n private watch(): void {\n if (this.watchTimer !== null || typeof setInterval !== \"function\") return;\n this.watchTimer = setInterval(() => {\n // `busy` covers the window before the portal has loaded (a slow session\n // request): the checkout is not open yet, but the watch is still needed\n // for when it closes afterwards.\n if (!this.busy && !this.isCheckoutOpen()) this.stopWatch();\n this.syncBusy();\n }, WATCH_INTERVAL_MS);\n }\n\n private stopWatch(): void {\n if (this.watchTimer === null) return;\n clearInterval(this.watchTimer);\n this.watchTimer = null;\n }\n}\n\n/**\n * Define `<esaalat-checkout-button>`. Safe to call repeatedly and on the\n * server (no `customElements`), so a bundler can import this module during\n * SSR without a guard of its own.\n *\n * Returns whether this call defined the element.\n */\nexport function registerEsaalatCheckoutButton(): boolean {\n if (typeof customElements === \"undefined\") return false;\n if (customElements.get(ESAALAT_CHECKOUT_BUTTON_TAG)) return false;\n customElements.define(ESAALAT_CHECKOUT_BUTTON_TAG, EsaalatCheckoutButtonElement);\n return true;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [ESAALAT_CHECKOUT_BUTTON_TAG]: EsaalatCheckoutButtonElement;\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -291,7 +291,19 @@ declare const ESAALAT_CHECKOUT_EVENTS: {
291
291
  readonly failed: "esaalat-failed";
292
292
  readonly error: "esaalat-error";
293
293
  };
294
- declare class EsaalatCheckoutButtonElement extends HTMLElement {
294
+ /**
295
+ * `HTMLElement` where it exists, an empty base where it does not.
296
+ *
297
+ * A custom element class cannot be declared against a global that Node does
298
+ * not have, and this module has to be importable during server rendering:
299
+ * Next renders client components on the server, so a static import of
300
+ * `esaalat-react` would otherwise throw `HTMLElement is not defined` before
301
+ * the browser ever gets the module. Nothing on the server instantiates the
302
+ * class, so the empty base is never used — `registerEsaalatCheckoutButton`
303
+ * stays a no-op without `customElements`.
304
+ */
305
+ declare const HTMLElementBase: typeof HTMLElement;
306
+ declare class EsaalatCheckoutButtonElement extends HTMLElementBase {
295
307
  static get observedAttributes(): string[];
296
308
  /** Called with the result when the wallet alert verified the payment. */
297
309
  onVerified?: (result: CheckoutResult) => void;
package/dist/index.d.ts CHANGED
@@ -291,7 +291,19 @@ declare const ESAALAT_CHECKOUT_EVENTS: {
291
291
  readonly failed: "esaalat-failed";
292
292
  readonly error: "esaalat-error";
293
293
  };
294
- declare class EsaalatCheckoutButtonElement extends HTMLElement {
294
+ /**
295
+ * `HTMLElement` where it exists, an empty base where it does not.
296
+ *
297
+ * A custom element class cannot be declared against a global that Node does
298
+ * not have, and this module has to be importable during server rendering:
299
+ * Next renders client components on the server, so a static import of
300
+ * `esaalat-react` would otherwise throw `HTMLElement is not defined` before
301
+ * the browser ever gets the module. Nothing on the server instantiates the
302
+ * class, so the empty base is never used — `registerEsaalatCheckoutButton`
303
+ * stays a no-op without `customElements`.
304
+ */
305
+ declare const HTMLElementBase: typeof HTMLElement;
306
+ declare class EsaalatCheckoutButtonElement extends HTMLElementBase {
295
307
  static get observedAttributes(): string[];
296
308
  /** Called with the result when the wallet alert verified the payment. */
297
309
  onVerified?: (result: CheckoutResult) => void;
package/dist/index.js CHANGED
@@ -1122,7 +1122,9 @@ function asError(error) {
1122
1122
  if (error instanceof Error) return error;
1123
1123
  return new EsaalatCheckoutError(String(error) || "The checkout failed.", "unavailable");
1124
1124
  }
1125
- var EsaalatCheckoutButtonElement = class extends HTMLElement {
1125
+ var HTMLElementBase = typeof HTMLElement === "undefined" ? class {
1126
+ } : HTMLElement;
1127
+ var EsaalatCheckoutButtonElement = class extends HTMLElementBase {
1126
1128
  constructor() {
1127
1129
  super(...arguments);
1128
1130
  /**
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/modal.ts","../src/window.ts","../src/client.ts","../src/element.ts"],"sourcesContent":["export type CheckoutErrorCode =\n | \"configuration\"\n | \"network\"\n | \"api\"\n | \"session\"\n | \"unavailable\"\n | \"aborted\";\n\nexport class EsaalatCheckoutError extends Error {\n readonly code: CheckoutErrorCode;\n readonly status?: number;\n readonly details?: unknown;\n\n constructor(\n message: string,\n code: CheckoutErrorCode,\n options: { status?: number; details?: unknown; cause?: unknown } = {}\n ) {\n super(message);\n this.name = \"EsaalatCheckoutError\";\n this.code = code;\n this.status = options.status;\n this.details = options.details;\n if (options.cause !== undefined) {\n // `cause` is ES2022; assigning it keeps the package ES2020-compatible.\n (this as Error & { cause?: unknown }).cause = options.cause;\n }\n }\n}\n","import type { CheckoutView } from \"./view\";\n\nexport interface CheckoutModalLabels {\n close: string;\n loading: string;\n errorTitle: string;\n}\n\ninterface CheckoutModalOptions {\n zIndex: number;\n title: string;\n labels: CheckoutModalLabels;\n onDismiss: () => void;\n}\n\nconst MODAL_CSS = `\n :host { all: initial; }\n *, *::before, *::after { box-sizing: border-box; }\n .overlay {\n position: fixed;\n inset: 0;\n z-index: 0;\n display: grid;\n place-items: center;\n padding: 12px;\n background: rgba(12, 11, 8, 0.58);\n -webkit-backdrop-filter: blur(7px);\n backdrop-filter: blur(7px);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n color: #0b0b0b;\n pointer-events: auto;\n animation: fade 180ms ease-out;\n }\n .dialog {\n position: relative;\n width: min(460px, calc(100vw - 24px));\n height: min(720px, calc(100dvh - 24px));\n overflow: hidden;\n border-radius: 22px;\n background: #fffefa;\n border: 1px solid rgba(255, 255, 255, 0.5);\n box-shadow: 0 36px 100px rgba(0, 0, 0, 0.4), 0 6px 24px rgba(0, 0, 0, 0.2);\n animation: rise 220ms cubic-bezier(0.2, 0.8, 0.2, 1);\n }\n .dialog.is-frame { background: #f3f0e8; }\n .chrome {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 14px 16px;\n border-bottom: 1px solid #e7e2d7;\n background: #fffefa;\n }\n .dialog.is-frame .chrome { display: none; }\n .mark {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n display: grid;\n place-items: center;\n background: #0b0b0b;\n color: #fff;\n font-size: 14px;\n font-weight: 800;\n flex-shrink: 0;\n }\n .chrome-title {\n font-size: 13px;\n font-weight: 700;\n line-height: 1.3;\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .close {\n width: 32px;\n height: 32px;\n display: grid;\n place-items: center;\n border: 0;\n border-radius: 9px;\n background: transparent;\n color: #716f67;\n cursor: pointer;\n flex-shrink: 0;\n }\n .close:hover { background: #f3f0e8; color: #0b0b0b; }\n .close:focus-visible { outline: 2px solid #0b0b0b; outline-offset: 2px; }\n .close svg { width: 18px; height: 18px; }\n .content {\n position: absolute;\n inset: 57px 0 0;\n overflow: hidden;\n }\n .dialog.is-frame .content { inset: 0; }\n .frame {\n display: block;\n width: 100%;\n height: 100%;\n border: 0;\n background: #f3f0e8;\n }\n .panel {\n height: 100%;\n display: grid;\n place-content: center;\n justify-items: center;\n gap: 12px;\n padding: 32px;\n text-align: center;\n }\n .spinner {\n width: 34px;\n height: 34px;\n border-radius: 50%;\n border: 2px solid #e7e2d7;\n border-top-color: #0b0b0b;\n animation: spin 900ms linear infinite;\n }\n .loading { font-size: 13px; color: #716f67; }\n .error-icon {\n width: 54px;\n height: 54px;\n border-radius: 50%;\n display: grid;\n place-items: center;\n background: #fef1ef;\n border: 1px solid #f5cfca;\n color: #b42318;\n }\n .error-icon svg { width: 25px; height: 25px; }\n .error-title { margin: 0; font-size: 17px; line-height: 1.4; }\n .error-message { margin: 0; font-size: 13px; line-height: 1.7; color: #716f67; max-width: 34ch; }\n .error-close {\n margin-top: 6px;\n min-height: 42px;\n padding: 9px 22px;\n border: 1px solid #e7e2d7;\n border-radius: 11px;\n background: transparent;\n color: #0b0b0b;\n font: inherit;\n font-size: 13px;\n font-weight: 700;\n cursor: pointer;\n }\n .error-close:hover { background: #f3f0e8; }\n .error-close:focus-visible { outline: 2px solid #0b0b0b; outline-offset: 2px; }\n @keyframes spin { to { transform: rotate(360deg); } }\n @keyframes fade { from { opacity: 0; } }\n @keyframes rise { from { opacity: 0; transform: translateY(10px) scale(0.985); } }\n @media (max-width: 520px) {\n .overlay { padding: 0; }\n .dialog {\n width: 100vw;\n height: 100dvh;\n max-height: none;\n border-radius: 0;\n border: 0;\n }\n .chrome { padding-top: calc(14px + env(safe-area-inset-top)); }\n }\n @media (prefers-color-scheme: dark) {\n .overlay { background: rgba(0, 0, 0, 0.7); }\n .dialog, .chrome { background: #1d1b17; border-color: #343028; color: #f6f2e8; }\n .dialog.is-frame, .frame { background: #141310; }\n .chrome-title { color: #f6f2e8; }\n .close { color: #aaa59a; }\n .close:hover { background: #2b2721; color: #f6f2e8; }\n .spinner { border-color: #343028; border-top-color: #f6f2e8; }\n .loading, .error-message { color: #aaa59a; }\n .error-icon { background: #2b1b19; border-color: #4b2c28; color: #f18d83; }\n .error-close { border-color: #343028; color: #f6f2e8; }\n .error-close:hover { background: #2b2721; }\n }\n @media (prefers-reduced-motion: reduce) {\n .overlay, .dialog { animation: none; }\n .spinner { animation-duration: 0.01ms; }\n }\n`;\n\nfunction element<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n className?: string\n): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n if (className) node.className = className;\n return node;\n}\n\nfunction closeSvg(): SVGSVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"1.8\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", \"M18 6 6 18M6 6l12 12\");\n svg.append(path);\n return svg;\n}\n\nfunction alertSvg(): SVGSVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"1.8\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", \"M12 9v4M12 17h.01M10.3 3.9 2.5 17.4A2 2 0 0 0 4.2 20h15.6a2 2 0 0 0 1.7-2.6L13.7 3.9a2 2 0 0 0-3.4 0Z\");\n svg.append(path);\n return svg;\n}\n\n/**\n * The modal lives in a shadow root so a merchant's global CSS cannot leak into\n * the checkout (or the other way around). The iframe is the only content once\n * the session is ready; the portal owns its own close button.\n */\nexport class CheckoutModal implements CheckoutView {\n private readonly host: HTMLDivElement;\n private readonly shadow: ShadowRoot;\n private readonly overlay: HTMLDivElement;\n private readonly dialog: HTMLDivElement;\n private readonly closeButton: HTMLButtonElement;\n private readonly content: HTMLDivElement;\n private frame: HTMLIFrameElement | null = null;\n private previousOverflow = \"\";\n private previousFocus: Element | null = null;\n private destroyed = false;\n\n onLoad: (() => void) | null = null;\n private readonly onDismiss: () => void;\n\n constructor(private readonly options: CheckoutModalOptions) {\n this.onDismiss = options.onDismiss;\n\n this.host = document.createElement(\"div\");\n this.host.setAttribute(\"data-esaalat-checkout\", \"\");\n this.host.style.cssText = `all: initial; position: fixed; inset: 0; z-index: ${options.zIndex}; pointer-events: none;`;\n\n this.shadow = this.host.attachShadow({ mode: \"open\" });\n const style = element(\"style\");\n style.textContent = MODAL_CSS;\n this.shadow.append(style);\n\n this.overlay = element(\"div\", \"overlay\");\n this.overlay.addEventListener(\"mousedown\", (event) => {\n if (event.target === this.overlay) this.onDismiss();\n });\n\n this.dialog = element(\"div\", \"dialog\");\n this.dialog.setAttribute(\"role\", \"dialog\");\n this.dialog.setAttribute(\"aria-modal\", \"true\");\n this.dialog.setAttribute(\"aria-label\", options.title);\n\n const chrome = element(\"div\", \"chrome\");\n const mark = element(\"span\", \"mark\");\n mark.textContent = \"E\";\n mark.setAttribute(\"aria-hidden\", \"true\");\n const title = element(\"span\", \"chrome-title\");\n title.textContent = options.title;\n\n this.closeButton = element(\"button\", \"close\");\n this.closeButton.type = \"button\";\n this.closeButton.setAttribute(\"aria-label\", options.labels.close);\n this.closeButton.append(closeSvg());\n this.closeButton.addEventListener(\"click\", () => this.onDismiss());\n\n chrome.append(mark, title, this.closeButton);\n\n this.content = element(\"div\", \"content\");\n this.showLoading();\n\n this.dialog.append(chrome, this.content);\n this.overlay.append(this.dialog);\n this.shadow.append(this.overlay);\n }\n\n open(): void {\n if (!document.body) {\n throw new Error(\"Esaalat checkout needs a document body.\");\n }\n this.previousOverflow = document.body.style.overflow;\n this.previousFocus = document.activeElement;\n document.body.style.overflow = \"hidden\";\n document.body.append(this.host);\n document.addEventListener(\"keydown\", this.handleKeyDown, true);\n this.closeButton.focus({ preventScroll: true });\n }\n\n load(url: string): void {\n if (this.destroyed) return;\n this.dialog.classList.add(\"is-frame\");\n this.content.replaceChildren();\n\n const frame = document.createElement(\"iframe\");\n frame.className = \"frame\";\n frame.src = url;\n frame.title = this.options.title;\n frame.setAttribute(\"allow\", \"clipboard-write\");\n frame.setAttribute(\"referrerpolicy\", \"strict-origin-when-cross-origin\");\n frame.setAttribute(\"loading\", \"eager\");\n frame.addEventListener(\"load\", () => {\n this.onLoad?.();\n try {\n frame.focus({ preventScroll: true });\n } catch {\n // focus is best-effort in embedded browsers\n }\n });\n\n this.frame = frame;\n this.content.append(frame);\n }\n\n get contentWindow(): Window | null {\n return this.frame?.contentWindow ?? null;\n }\n\n showError(message: string): void {\n if (this.destroyed) return;\n this.content.replaceChildren();\n\n const panel = element(\"div\", \"panel\");\n const icon = element(\"span\", \"error-icon\");\n icon.append(alertSvg());\n const title = element(\"h2\", \"error-title\");\n title.textContent = this.options.labels.errorTitle;\n const text = element(\"p\", \"error-message\");\n text.textContent = message;\n const close = element(\"button\", \"error-close\");\n close.type = \"button\";\n close.textContent = this.options.labels.close;\n close.addEventListener(\"click\", () => this.onDismiss());\n\n panel.append(icon, title, text, close);\n this.content.append(panel);\n this.dialog.classList.remove(\"is-frame\");\n close.focus({ preventScroll: true });\n }\n\n private showLoading(): void {\n this.content.replaceChildren();\n const panel = element(\"div\", \"panel\");\n const spinner = element(\"span\", \"spinner\");\n spinner.setAttribute(\"aria-hidden\", \"true\");\n const label = element(\"p\", \"loading\");\n label.textContent = this.options.labels.loading;\n panel.append(spinner, label);\n this.content.append(panel);\n }\n\n private handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n this.onDismiss();\n }\n };\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n document.removeEventListener(\"keydown\", this.handleKeyDown, true);\n document.body.style.overflow = this.previousOverflow;\n this.host.remove();\n if (this.previousFocus instanceof HTMLElement && this.previousFocus.isConnected) {\n try {\n this.previousFocus.focus({ preventScroll: true });\n } catch {\n // ignore\n }\n }\n this.onLoad = null;\n this.frame = null;\n }\n}\n","import type { CheckoutView } from \"./view\";\n\nexport interface CheckoutWindowOptions {\n title: string;\n labels: {\n loading: string;\n errorTitle: string;\n close: string;\n };\n dir: \"rtl\" | \"ltr\";\n lang: string;\n onDismiss: () => void;\n}\n\nconst WINDOW_NAME = \"esaalat-checkout\";\nconst WINDOW_WIDTH = 480;\nconst WINDOW_HEIGHT = 800;\nconst CLOSE_POLL_MS = 400;\n\nconst DOC_CSS = `\n * { box-sizing: border-box; }\n html, body { height: 100%; }\n body {\n margin: 0;\n display: grid;\n place-items: center;\n padding: 24px;\n background: #f3f0e8;\n color: #0b0b0b;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n }\n .panel {\n display: grid;\n justify-items: center;\n gap: 14px;\n max-width: 34ch;\n text-align: center;\n }\n .error-icon {\n width: 54px;\n height: 54px;\n border-radius: 50%;\n display: grid;\n place-items: center;\n background: #fef1ef;\n border: 1px solid #f5cfca;\n color: #b42318;\n font-size: 24px;\n font-weight: 800;\n }\n .error-title { margin: 0; font-size: 17px; line-height: 1.4; }\n .error-message { margin: 0; font-size: 13px; line-height: 1.7; color: #716f67; }\n .error-close {\n margin-top: 4px;\n min-height: 42px;\n padding: 9px 22px;\n border: 1px solid #ded7c8;\n border-radius: 11px;\n background: transparent;\n color: #0b0b0b;\n font: inherit;\n font-size: 13px;\n font-weight: 700;\n cursor: pointer;\n }\n .error-close:hover { background: #e9e4d8; }\n @media (prefers-color-scheme: dark) {\n body { background: #141310; color: #f6f2e8; }\n .error-message { color: #aaa59a; }\n .error-icon { background: #2b1b19; border-color: #4b2c28; color: #f18d83; }\n .error-close { border-color: #343028; color: #f6f2e8; }\n .error-close:hover { background: #2b2721; }\n }\n`;\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\n/** A centered popup, sized like the checkout card it replaces. */\nfunction windowFeatures(): string {\n const screenWidth = window.screen?.availWidth ?? WINDOW_WIDTH;\n const screenHeight = window.screen?.availHeight ?? WINDOW_HEIGHT;\n const width = Math.min(WINDOW_WIDTH, Math.max(320, screenWidth - 40));\n const height = Math.min(WINDOW_HEIGHT, Math.max(480, screenHeight - 40));\n const baseX = typeof window.screenX === \"number\" ? window.screenX : 0;\n const baseY = typeof window.screenY === \"number\" ? window.screenY : 0;\n const outerWidth = window.outerWidth || width;\n const outerHeight = window.outerHeight || height;\n const left = Math.max(0, Math.round(baseX + (outerWidth - width) / 2));\n const top = Math.max(0, Math.round(baseY + (outerHeight - height) / 2));\n\n return [\n \"popup=yes\",\n `width=${width}`,\n `height=${height}`,\n `left=${left}`,\n `top=${top}`,\n \"resizable=yes\",\n \"scrollbars=yes\",\n ].join(\",\");\n}\n\nfunction documentHtml(\n title: string,\n dir: \"rtl\" | \"ltr\",\n lang: string,\n body: string\n): string {\n return [\n \"<!doctype html>\",\n `<html dir=\"${dir}\" lang=\"${lang}\">`,\n \"<head>\",\n '<meta charset=\"utf-8\" />',\n '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />',\n '<meta name=\"robots\" content=\"noindex\" />',\n `<title>${escapeHtml(title)}</title>`,\n `<style>${DOC_CSS}</style>`,\n \"</head>\",\n `<body>${body}</body>`,\n \"</html>\",\n ].join(\"\");\n}\n\n/**\n * Opens the hosted checkout in its own browser window.\n *\n * The window has to be requested synchronously from the buyer's click, before\n * the session request, or every popup blocker swallows it — so the constructor\n * opens a blank window with a \"preparing checkout\" page and `load()` navigates\n * it once the session exists.\n *\n * The merchant page keeps talking to the portal with `postMessage`: the window\n * handle stays valid across the navigation, and the portal answers the opener\n * (see `createEmbeddedBridge`).\n */\nexport class CheckoutWindow implements CheckoutView {\n private readonly win: Window;\n private readonly onDismiss: () => void;\n private readonly dir: \"rtl\" | \"ltr\";\n private readonly lang: string;\n private readonly title: string;\n private readonly labels: CheckoutWindowOptions[\"labels\"];\n private pollId: number | null = null;\n private navigated = false;\n private destroyed = false;\n\n onLoad: (() => void) | null = null;\n\n constructor(options: CheckoutWindowOptions) {\n const opened = window.open(\"\", WINDOW_NAME, windowFeatures());\n if (!opened) {\n throw new Error(\"The browser blocked the checkout window.\");\n }\n\n this.win = opened;\n this.onDismiss = options.onDismiss;\n this.title = options.title;\n this.labels = options.labels;\n this.dir = options.dir;\n this.lang = options.lang;\n\n this.pollId = window.setInterval(() => this.checkClosed(), CLOSE_POLL_MS);\n\n try {\n this.win.focus();\n } catch {\n // focus is best-effort in embedded browsers\n }\n }\n\n get contentWindow(): Window | null {\n return this.win;\n }\n\n open(): void {\n try {\n this.win.focus();\n } catch {\n // focus is best-effort\n }\n }\n\n load(url: string): void {\n if (this.destroyed) return;\n this.navigated = true;\n try {\n // `replace` keeps the empty window out of the buyer's back history.\n this.win.location.replace(url);\n } catch {\n if (this.win.closed) {\n this.dismiss();\n return;\n }\n // Some embedded browsers refuse one navigation call but accept another.\n try {\n this.win.location.href = url;\n } catch {\n // The portal never loaded; the close poll will notice if it is gone.\n }\n }\n this.onLoad?.();\n }\n\n showError(message: string): void {\n // After the navigation the portal owns that document; nothing safe to paint.\n if (this.destroyed || this.navigated) return;\n\n this.renderError(\n documentHtml(\n this.title,\n this.dir,\n this.lang,\n `<div class=\"panel\">` +\n `<span class=\"error-icon\" aria-hidden=\"true\">!</span>` +\n `<h2 class=\"error-title\">${escapeHtml(this.labels.errorTitle)}</h2>` +\n `<p class=\"error-message\">${escapeHtml(message)}</p>` +\n `<button class=\"error-close\" type=\"button\">${escapeHtml(this.labels.close)}</button>` +\n `</div>`\n )\n );\n\n try {\n const close = this.win.document.querySelector(\".error-close\");\n close?.addEventListener(\"click\", () => this.onDismiss());\n } catch {\n // The window went away before the close button could be wired.\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.stopPolling();\n this.onLoad = null;\n try {\n this.win.close();\n } catch {\n // Already closed by the buyer.\n }\n }\n\n /**\n * Best-effort: the placeholder document is cosmetic. A refused write must\n * never cancel the checkout — the navigation below still has to happen.\n */\n private renderError(html: string): void {\n try {\n const doc = this.win.document;\n doc.open();\n doc.write(html);\n doc.close();\n } catch {\n // Browser refused to let us paint into the blank window.\n }\n }\n\n private checkClosed(): void {\n if (this.destroyed) {\n this.stopPolling();\n return;\n }\n if (this.win.closed) this.dismiss();\n }\n\n private dismiss(): void {\n if (this.destroyed) return;\n this.stopPolling();\n this.onDismiss();\n }\n\n private stopPolling(): void {\n if (this.pollId !== null) {\n window.clearInterval(this.pollId);\n this.pollId = null;\n }\n }\n}\n","import { EsaalatCheckoutError } from \"./errors\";\nimport { CheckoutModal } from \"./modal\";\nimport type {\n CheckoutBeforeCreateOrderHandler,\n CheckoutCreatePayload,\n CheckoutItem,\n CheckoutLocale,\n CheckoutOpenOptions,\n CheckoutPresentation,\n CheckoutResult,\n CheckoutResultReason,\n CheckoutResultStatus,\n CheckoutSession,\n EsaalatCheckoutOptions,\n} from \"./types\";\nimport type { CheckoutView } from \"./view\";\nimport { CheckoutWindow } from \"./window\";\n\nconst DEFAULT_API_BASE = \"https://api.esaalat.com/api/v1\";\nconst DEFAULT_PORTAL_BASE = \"https://pay.esaalat.com\";\nconst SDK_VERSION = \"0.1.0\";\nconst REQUEST_TIMEOUT_MS = 20_000;\nconst INIT_RETRY_MS = 300;\n// A browser window needs longer than an iframe: the init message races the\n// navigation, so keep knocking until the portal answers `ready`.\nconst INIT_ATTEMPTS = 100;\nconst VERIFIED_CLOSE_MS = 1_800;\nconst ERROR_CLOSE_MS = 6_000;\n\nconst RESULT_STATUSES: CheckoutResultStatus[] = [\n \"VERIFIED\",\n \"WRONG_AMOUNT\",\n \"EXPIRED\",\n \"CANCELLED\",\n \"FAILED\",\n];\n\nconst RESULT_REASONS: CheckoutResultReason[] = [\n \"dismissed\",\n \"destroyed\",\n \"intent_cancelled\",\n \"session_expired\",\n \"session_not_found\",\n \"network_error\",\n];\n\ninterface ActiveCheckout {\n token: string | null;\n locale: CheckoutLocale;\n controller: AbortController;\n view: CheckoutView;\n settled: boolean;\n resolve: (result: CheckoutResult) => void;\n reject: (error: Error) => void;\n onResult?: (result: CheckoutResult) => void;\n}\n\ninterface PortalMessage {\n source?: unknown;\n type?: unknown;\n sessionToken?: unknown;\n payload?: unknown;\n}\n\ninterface PortalResultPayload {\n status?: unknown;\n reason?: unknown;\n intentCode?: unknown;\n amount?: unknown;\n paidAmount?: unknown;\n currency?: unknown;\n externalOrderId?: unknown;\n merchantName?: unknown;\n}\n\nfunction normalizeBase(value: string, fallback: string): string {\n const raw = value.trim() || fallback;\n let url: URL;\n try {\n const base =\n typeof window !== \"undefined\" ? window.location?.href : undefined;\n url = new URL(raw, base);\n } catch {\n throw new EsaalatCheckoutError(\n `Invalid URL: ${raw}`,\n \"configuration\"\n );\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new EsaalatCheckoutError(\n `Unsupported URL protocol: ${url.protocol}`,\n \"configuration\"\n );\n }\n return url.toString().replace(/\\/+$/, \"\");\n}\n\nfunction requestId(): string {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n // UUID v4 fallback for older embedded browsers.\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (char) => {\n const random = (Math.random() * 16) | 0;\n const value = char === \"x\" ? random : (random & 0x3) | 0x8;\n return value.toString(16);\n });\n}\n\nfunction stringOr(value: unknown, fallback = \"\"): string {\n return typeof value === \"string\" ? value : fallback;\n}\n\nfunction nullOrString(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction errorDetail(body: unknown): string | null {\n if (!body || typeof body !== \"object\") return null;\n const record = body as Record<string, unknown>;\n if (typeof record.detail === \"string\") return record.detail;\n if (Array.isArray(record.errors)) {\n for (const error of record.errors) {\n if (error && typeof error === \"object\") {\n const detail = (error as Record<string, unknown>).detail;\n if (typeof detail === \"string\") return detail;\n }\n }\n }\n for (const value of Object.values(record)) {\n if (typeof value === \"string\") return value;\n if (Array.isArray(value) && typeof value[0] === \"string\") return value[0];\n }\n return null;\n}\n\nfunction isCheckoutSession(value: unknown): value is CheckoutSession {\n if (!value || typeof value !== \"object\") return false;\n const record = value as Record<string, unknown>;\n return (\n typeof record.session_token === \"string\" &&\n typeof record.portal_url === \"string\" &&\n typeof record.amount === \"string\" &&\n typeof record.currency === \"string\"\n );\n}\n\nfunction cancelledResult(\n token: string | null,\n reason: \"dismissed\" | \"destroyed\"\n): CheckoutResult {\n return {\n status: \"CANCELLED\",\n reason,\n sessionToken: token ?? \"\",\n intentCode: null,\n amount: \"0.00\",\n paidAmount: null,\n currency: \"YER\",\n externalOrderId: \"\",\n merchantName: \"\",\n };\n}\n\n/**\n * Framework-agnostic Esaalat checkout client.\n *\n * It creates a checkout session with the merchant's publishable key, opens the\n * Esaalat-hosted portal in its own browser window (or an in-page modal when\n * asked, or when the browser blocks the window), and resolves `open()` with a\n * terminal result. The publishable key is public by design; keep the client\n * secret and any order confirmation on the server.\n */\nexport class EsaalatCheckout {\n private readonly publishableKey: string;\n private readonly apiBaseUrl: string;\n private readonly portalBaseUrl: string;\n private readonly zIndex: number;\n private readonly presentation: CheckoutPresentation;\n private readonly locale: CheckoutLocale;\n private readonly fetchImpl: typeof fetch | null;\n private readonly defaultOnResult?: (result: CheckoutResult) => void;\n private readonly defaultOnError?: (error: Error) => void;\n\n private active: ActiveCheckout | null = null;\n private view: CheckoutView | null = null;\n private portalOrigin: string | null = null;\n private sessionToken: string | null = null;\n private initTimer: number | null = null;\n private verifiedTimer: number | null = null;\n private errorTimer: number | null = null;\n\n constructor(options: EsaalatCheckoutOptions) {\n // The key is only needed to create a session in the browser. A merchant\n // that opens a server-created session passes its token instead, so an\n // empty key is allowed here and refused by `open()` only on the create\n // path.\n const key =\n typeof options?.publishableKey === \"string\"\n ? options.publishableKey.trim()\n : \"\";\n\n this.publishableKey = key;\n this.locale =\n options.locale === \"en\" || options.locale === \"ar\" ? options.locale : \"ar\";\n this.apiBaseUrl = normalizeBase(options.apiBaseUrl ?? \"\", DEFAULT_API_BASE);\n this.portalBaseUrl = normalizeBase(\n options.portalBaseUrl ?? \"\",\n DEFAULT_PORTAL_BASE\n );\n this.zIndex =\n typeof options.zIndex === \"number\" && Number.isFinite(options.zIndex)\n ? options.zIndex\n : 2_147_483_000;\n this.presentation =\n options.presentation === \"modal\" ? \"modal\" : \"window\";\n\n const fetchFromOptions = options.fetch;\n const globalFetch =\n typeof fetch === \"function\" ? fetch.bind(globalThis) : null;\n this.fetchImpl = fetchFromOptions ?? globalFetch;\n this.defaultOnResult = options.onResult;\n this.defaultOnError = options.onError;\n }\n\n /** True while a checkout window or modal is on screen. */\n get isOpen(): boolean {\n return this.view !== null;\n }\n\n /**\n * Open the hosted checkout and resolve with its terminal result.\n *\n * A second call while a checkout is open rejects; close the first one with\n * `close()` or wait for its result.\n */\n async open(options: CheckoutOpenOptions = {}): Promise<CheckoutResult> {\n if (this.active || this.view) {\n throw new EsaalatCheckoutError(\n \"A checkout is already open. Close it before starting another.\",\n \"configuration\"\n );\n }\n if (!this.fetchImpl) {\n throw new EsaalatCheckoutError(\n \"This browser does not support fetch. Use the SDK on a modern browser.\",\n \"configuration\"\n );\n }\n\n const locale =\n options.locale === \"en\" || options.locale === \"ar\"\n ? options.locale\n : this.locale;\n const items = options.items ?? [];\n const existingToken = options.sessionToken?.trim() || null;\n const hasAmount =\n options.amount !== undefined &&\n options.amount !== null &&\n String(options.amount).trim() !== \"\";\n if (!existingToken && !this.publishableKey) {\n throw new EsaalatCheckoutError(\n \"A publishable key is required to create a session. Pass one, or open a server-created `sessionToken`.\",\n \"configuration\"\n );\n }\n if (!existingToken && !hasAmount && items.length === 0) {\n throw new EsaalatCheckoutError(\n \"Provide an amount, items, or a server-created session token.\",\n \"configuration\"\n );\n }\n if (!existingToken && items.length > 0) {\n for (const item of items) {\n if (!item.name || item.price === undefined || item.price === null) {\n throw new EsaalatCheckoutError(\n \"Every item needs a name and a price.\",\n \"configuration\"\n );\n }\n }\n }\n\n const labels =\n locale === \"ar\"\n ? {\n close: \"إغلاق\",\n loading: \"جارٍ تجهيز الدفع الآمن…\",\n errorTitle: \"تعذّر بدء الدفع\",\n }\n : {\n close: \"Close\",\n loading: \"Preparing secure checkout…\",\n errorTitle: \"Couldn't start the checkout\",\n };\n\n const presentation: CheckoutPresentation =\n options.presentation === \"window\" || options.presentation === \"modal\"\n ? options.presentation\n : this.presentation;\n\n // The view is created before the first `await`: a browser window has to be\n // requested inside the buyer's click, or popup blockers discard it.\n let view: CheckoutView;\n try {\n view = this.createView(presentation, labels, locale);\n view.open();\n } catch (error) {\n throw new EsaalatCheckoutError(\n \"The checkout could not be opened.\",\n \"unavailable\",\n { cause: error }\n );\n }\n\n const controller = new AbortController();\n let resolvePromise!: (result: CheckoutResult) => void;\n let rejectPromise!: (error: Error) => void;\n const promise = new Promise<CheckoutResult>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n });\n\n const onResult = options.onResult ?? this.defaultOnResult;\n const onError = options.onError ?? this.defaultOnError;\n\n const active: ActiveCheckout = {\n token: null,\n locale,\n controller,\n view,\n settled: false,\n resolve: resolvePromise,\n reject: rejectPromise,\n onResult,\n };\n this.active = active;\n this.view = view;\n this.sessionToken = null;\n this.portalOrigin = null;\n\n view.onLoad = () => this.startInitRetry();\n\n let portalUrl: string;\n try {\n if (existingToken) {\n active.token = existingToken;\n this.sessionToken = existingToken;\n portalUrl = this.buildPortalUrl(\n existingToken,\n options.portalUrl ?? \"\",\n locale\n );\n } else {\n const session = await this.createSession(\n options,\n locale,\n controller.signal\n );\n // The buyer closed the checkout while the session was being created.\n if (active.settled) return promise;\n active.token = session.session_token;\n this.sessionToken = session.session_token;\n portalUrl = this.buildPortalUrl(\n session.session_token,\n session.portal_url,\n locale\n );\n }\n this.portalOrigin = new URL(portalUrl).origin;\n } catch (error) {\n if (active.settled) return promise;\n const wrapped =\n error instanceof EsaalatCheckoutError\n ? error\n : new EsaalatCheckoutError(\n \"Esaalat returned an invalid checkout URL.\",\n \"session\",\n { cause: error }\n );\n active.settled = true;\n this.active = null;\n this.removeMessageListener();\n try {\n onError?.(wrapped);\n } catch {\n // A merchant callback must not prevent the promise from settling.\n }\n active.reject(wrapped);\n view.showError(wrapped.message);\n this.errorTimer = window.setTimeout(() => {\n if (this.view === view) this.teardown();\n }, ERROR_CLOSE_MS);\n return promise;\n }\n\n window.addEventListener(\"message\", this.handleMessage);\n view.load(portalUrl);\n return promise;\n }\n\n /** Close the checkout. An in-flight `open()` resolves with CANCELLED. */\n close(): void {\n if (this.active) {\n this.dismiss();\n return;\n }\n this.teardown();\n }\n\n /** Remove the checkout view and any listeners without resolving a result. */\n destroy(): void {\n if (this.active && !this.active.settled) {\n this.finish(cancelledResult(this.sessionToken, \"destroyed\"));\n return;\n }\n this.teardown();\n }\n\n private createView(\n presentation: CheckoutPresentation,\n labels: { close: string; loading: string; errorTitle: string },\n locale: CheckoutLocale\n ): CheckoutView {\n const title =\n locale === \"ar\" ? \"إيصالات — دفع آمن\" : \"Esaalat — Secure checkout\";\n const onDismiss = () => this.dismiss();\n\n if (presentation === \"window\") {\n try {\n return new CheckoutWindow({\n title,\n labels,\n dir: locale === \"ar\" ? \"rtl\" : \"ltr\",\n lang: locale,\n onDismiss,\n });\n } catch {\n // The popup was blocked (or there is no window): the modal is the\n // always-available fallback, so the buyer still gets to pay.\n }\n }\n\n return new CheckoutModal({\n zIndex: this.zIndex,\n title,\n labels,\n onDismiss,\n });\n }\n\n private buildPortalUrl(\n sessionToken: string,\n rawPortalUrl: string,\n locale: CheckoutLocale\n ): string {\n const raw =\n rawPortalUrl.trim() ||\n `${this.portalBaseUrl}/checkout/${encodeURIComponent(sessionToken)}`;\n const url = new URL(raw);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new Error(\"Unsupported portal protocol\");\n }\n url.searchParams.set(\"lang\", locale);\n return url.toString();\n }\n\n private async createSession(\n options: CheckoutOpenOptions,\n locale: CheckoutLocale,\n outerSignal: AbortSignal\n ): Promise<CheckoutSession> {\n if (!this.fetchImpl) {\n throw new EsaalatCheckoutError(\"fetch is unavailable\", \"configuration\");\n }\n\n let payload: CheckoutCreatePayload = {};\n if (options.amount !== undefined && options.amount !== null) {\n payload.amount = String(options.amount);\n }\n if (options.items?.length) {\n payload.items = options.items.map((item: CheckoutItem) => ({\n name: item.name,\n ...(item.description ? { description: item.description } : {}),\n price: String(item.price),\n quantity: item.quantity ?? 1,\n }));\n }\n if (options.currency) payload.currency = options.currency;\n if (options.externalOrderId) {\n payload.external_order_id = options.externalOrderId;\n }\n if (options.notes) payload.notes = options.notes;\n if (options.wallet) payload.wallet = options.wallet;\n\n // The merchant's last word on what is sent. Whatever this throws becomes\n // the checkout's own error, so a veto reaches `open()` as `configuration`\n // with the merchant's message instead of being swallowed.\n const beforeCreate: CheckoutBeforeCreateOrderHandler | undefined =\n options.onBeforeCreateOrder;\n if (beforeCreate) {\n let updated: CheckoutCreatePayload | void;\n try {\n updated = await beforeCreate(payload);\n } catch (error) {\n throw new EsaalatCheckoutError(\n error instanceof Error && error.message\n ? error.message\n : locale === \"ar\"\n ? \"أُلغي الدفع.\"\n : \"The checkout was cancelled.\",\n \"configuration\",\n { cause: error }\n );\n }\n if (updated && typeof updated === \"object\") payload = updated;\n }\n\n const controller = new AbortController();\n let timedOut = false;\n const timeout = window.setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, REQUEST_TIMEOUT_MS);\n const abortOuter = () => controller.abort();\n outerSignal.addEventListener(\"abort\", abortOuter);\n\n try {\n const response = await this.fetchImpl(\n `${this.apiBaseUrl}/checkout/sdk/sessions/`,\n {\n method: \"POST\",\n credentials: \"omit\",\n cache: \"no-store\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n \"ESAALAT-PUBLISHABLE-KEY\": this.publishableKey,\n \"ESAALAT-IDEMPOTENCY-KEY\":\n options.idempotencyKey?.trim() || requestId(),\n \"ESAALAT-SDK-VERSION\": SDK_VERSION,\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n }\n );\n\n const session: unknown = await response.json().catch(() => null);\n if (!response.ok) {\n throw new EsaalatCheckoutError(\n errorDetail(session) ||\n (locale === \"ar\"\n ? \"تعذّر إنشاء جلسة الدفع.\"\n : \"Couldn't create the checkout session.\"),\n \"api\",\n { status: response.status, details: session }\n );\n }\n if (!isCheckoutSession(session)) {\n throw new EsaalatCheckoutError(\n \"Esaalat returned an invalid checkout session.\",\n \"session\",\n { details: session }\n );\n }\n\n // The session exists; a broken listener must not kill the payment.\n try {\n options.onOrderCreated?.(session);\n } catch {\n // Ignored on purpose.\n }\n\n return session;\n } catch (error) {\n if (error instanceof EsaalatCheckoutError) throw error;\n if (timedOut) {\n throw new EsaalatCheckoutError(\n locale === \"ar\"\n ? \"انتهت مهلة الاتصال بإيصالات. حاول مرة أخرى.\"\n : \"The connection to Esaalat timed out. Please try again.\",\n \"network\",\n { cause: error }\n );\n }\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw error;\n }\n throw new EsaalatCheckoutError(\n locale === \"ar\"\n ? \"تعذّر الاتصال بإيصالات. تحقق من اتصالك وحاول مرة أخرى.\"\n : \"Couldn't reach Esaalat. Check your connection and try again.\",\n \"network\",\n { cause: error }\n );\n } finally {\n window.clearTimeout(timeout);\n outerSignal.removeEventListener(\"abort\", abortOuter);\n }\n }\n\n private startInitRetry(): void {\n this.clearInitTimer();\n let attempts = 0;\n\n const tick = () => {\n if (!this.view || !this.portalOrigin || !this.sessionToken) return;\n this.postInit();\n attempts += 1;\n if (attempts < INIT_ATTEMPTS) {\n this.initTimer = window.setTimeout(tick, INIT_RETRY_MS);\n } else {\n this.initTimer = null;\n }\n };\n\n tick();\n }\n\n private postInit(): void {\n const target = this.view?.contentWindow;\n if (!target || !this.portalOrigin || !this.sessionToken) return;\n const message = {\n source: \"esaalat-checkout-sdk\",\n version: 1,\n type: \"init\",\n sessionToken: this.sessionToken,\n parentOrigin: window.location.origin,\n locale: this.active?.locale ?? this.locale,\n };\n try {\n target.postMessage(message, this.portalOrigin);\n } catch {\n // The iframe may have been torn down between the check and the post.\n }\n }\n\n private clearInitTimer(): void {\n if (this.initTimer !== null) {\n window.clearTimeout(this.initTimer);\n this.initTimer = null;\n }\n }\n\n private handleMessage = (event: MessageEvent): void => {\n if (!this.view || !this.portalOrigin) return;\n if (event.source !== this.view.contentWindow) return;\n if (event.origin !== this.portalOrigin) return;\n\n const data = event.data as PortalMessage | null;\n if (!data || typeof data !== \"object\") return;\n if (data.source !== \"esaalat-checkout\") return;\n if (data.sessionToken !== this.sessionToken) return;\n\n if (data.type === \"ready\") {\n this.clearInitTimer();\n return;\n }\n\n if (data.type === \"close\") {\n this.dismiss();\n return;\n }\n\n if (data.type === \"result\") {\n const result = this.parseResult(data.payload);\n if (result) this.finish(result);\n }\n };\n\n private parseResult(payload: unknown): CheckoutResult | null {\n if (!payload || typeof payload !== \"object\") return null;\n const value = payload as PortalResultPayload;\n if (\n typeof value.status !== \"string\" ||\n !RESULT_STATUSES.includes(value.status as CheckoutResultStatus)\n ) {\n return null;\n }\n\n const reason =\n typeof value.reason === \"string\" &&\n RESULT_REASONS.includes(value.reason as CheckoutResultReason)\n ? (value.reason as CheckoutResultReason)\n : undefined;\n\n return {\n status: value.status as CheckoutResultStatus,\n ...(reason ? { reason } : {}),\n sessionToken: this.sessionToken ?? \"\",\n intentCode: nullOrString(value.intentCode),\n amount: stringOr(value.amount, \"0.00\"),\n paidAmount: nullOrString(value.paidAmount),\n currency: stringOr(value.currency, \"YER\"),\n externalOrderId: stringOr(value.externalOrderId),\n merchantName: stringOr(value.merchantName),\n };\n }\n\n private finish(result: CheckoutResult): void {\n const active = this.active;\n if (!active || active.settled) return;\n\n active.settled = true;\n this.active = null;\n this.clearInitTimer();\n active.controller.abort();\n try {\n active.onResult?.(result);\n } catch {\n // A merchant callback must not prevent the promise from settling.\n }\n active.resolve(result);\n\n if (result.reason === \"dismissed\" || result.reason === \"destroyed\") {\n this.teardown();\n return;\n }\n\n if (result.status === \"VERIFIED\") {\n this.verifiedTimer = window.setTimeout(() => this.teardown(), VERIFIED_CLOSE_MS);\n }\n // Other terminal states stay visible until the buyer closes them, so the\n // reason (wrong amount, expiry, cancellation) is not flashed away.\n }\n\n private dismiss(): void {\n if (this.active && !this.active.settled) {\n this.finish(cancelledResult(this.sessionToken, \"dismissed\"));\n return;\n }\n this.teardown();\n }\n\n private removeMessageListener(): void {\n window.removeEventListener(\"message\", this.handleMessage);\n }\n\n private clearTimers(): void {\n this.clearInitTimer();\n if (this.verifiedTimer !== null) {\n window.clearTimeout(this.verifiedTimer);\n this.verifiedTimer = null;\n }\n if (this.errorTimer !== null) {\n window.clearTimeout(this.errorTimer);\n this.errorTimer = null;\n }\n }\n\n private teardown(): void {\n this.clearTimers();\n this.removeMessageListener();\n if (this.view) {\n this.view.destroy();\n this.view = null;\n }\n this.portalOrigin = null;\n this.sessionToken = null;\n this.active = null;\n }\n}\n","import { EsaalatCheckout } from \"./client\";\nimport { EsaalatCheckoutError } from \"./errors\";\nimport type {\n CheckoutBeforeCreateOrderHandler,\n CheckoutItem,\n CheckoutLocale,\n CheckoutOpenOptions,\n CheckoutPresentation,\n CheckoutResult,\n CheckoutResultStatus,\n CheckoutSession,\n} from \"./types\";\n\n/**\n * A \"Pay with Esaalat\" button that any framework can render.\n *\n * It is a custom element, not a React/Vue/Angular component, because the\n * checkout is one behaviour that should not be reimplemented per framework:\n * the same tag and the same attributes work in plain HTML, in a Vue template\n * (`@esaalat-verified`), in an Angular template (`(esaalat-verified)` with\n * `CUSTOM_ELEMENTS_SCHEMA`) and — through `esaalat-react`, which only sets\n * properties and listeners — in JSX.\n *\n * The element is a thin shell over `EsaalatCheckout`: a click calls `open()`\n * with the attributes as options, and the terminal result is routed to ONE\n * named callback per outcome (see `OUTCOMES`). Nothing here re-implements the\n * portal, the session API or the result contract.\n *\n * ```html\n * <esaalat-checkout-button\n * publishable-key=\"pk_live_...\"\n * amount=\"5000.00\"\n * external-order-id=\"order-123\"\n * ></esaalat-checkout-button>\n * <script>\n * const button = document.querySelector(\"esaalat-checkout-button\");\n * button.onVerified = (result) => console.log(result.intentCode);\n * button.onCancelled = () => console.log(\"not this time\");\n * </script>\n * ```\n */\n\n/** The tag this element is registered under. */\nexport const ESAALAT_CHECKOUT_BUTTON_TAG = \"esaalat-checkout-button\";\n\n/** Label shown when the merchant passes neither `label` nor child text. */\nconst DEFAULT_LABELS: Record<CheckoutLocale, string> = {\n ar: \"ادفع الآن\",\n en: \"Pay now\",\n};\n\ntype HandlerName =\n | \"onVerified\"\n | \"onCancelled\"\n | \"onWrongAmount\"\n | \"onExpired\"\n | \"onFailed\";\n\n/**\n * One callback per terminal status: the buyer's outcome picks exactly one row,\n * so a merchant never has to switch on `result.status` to find the interesting\n * case. `FAILED` is a result (the portal could not load a valid session), not a\n * thrown error — `onError` stays reserved for `open()` rejecting.\n */\nconst OUTCOMES: Record<\n CheckoutResultStatus,\n { handler: HandlerName; event: string }\n> = {\n VERIFIED: { handler: \"onVerified\", event: \"esaalat-verified\" },\n CANCELLED: { handler: \"onCancelled\", event: \"esaalat-cancelled\" },\n WRONG_AMOUNT: { handler: \"onWrongAmount\", event: \"esaalat-wrong-amount\" },\n EXPIRED: { handler: \"onExpired\", event: \"esaalat-expired\" },\n FAILED: { handler: \"onFailed\", event: \"esaalat-failed\" },\n};\n\n/** Names of the DOM events, exported for `addEventListener` users. */\nexport const ESAALAT_CHECKOUT_EVENTS = {\n verified: \"esaalat-verified\",\n cancelled: \"esaalat-cancelled\",\n wrongAmount: \"esaalat-wrong-amount\",\n expired: \"esaalat-expired\",\n failed: \"esaalat-failed\",\n error: \"esaalat-error\",\n} as const;\n\n/** How often the button re-checks whether its checkout has been closed. */\nconst WATCH_INTERVAL_MS = 300;\n\nfunction asError(error: unknown): Error {\n if (error instanceof Error) return error;\n return new EsaalatCheckoutError(String(error) || \"The checkout failed.\", \"unavailable\");\n}\n\nexport class EsaalatCheckoutButtonElement extends HTMLElement {\n static get observedAttributes(): string[] {\n return [\n \"publishable-key\",\n \"amount\",\n \"currency\",\n \"external-order-id\",\n \"notes\",\n \"wallet\",\n \"locale\",\n \"presentation\",\n \"session-token\",\n \"portal-url\",\n \"label\",\n \"disabled\",\n \"items\",\n ];\n }\n\n /** Called with the result when the wallet alert verified the payment. */\n onVerified?: (result: CheckoutResult) => void;\n /** Called when the buyer dismissed the checkout, or the intent was cancelled. */\n onCancelled?: (result: CheckoutResult) => void;\n /** Called when a payment matched but for a different amount. */\n onWrongAmount?: (result: CheckoutResult) => void;\n /** Called when the buyer ran out of time. */\n onExpired?: (result: CheckoutResult) => void;\n /** Called when the portal could not load a valid session. */\n onFailed?: (result: CheckoutResult) => void;\n /** Called when `open()` rejects (configuration, network, API or unavailable). */\n onError?: (error: Error) => void;\n\n /**\n * Called just before this button creates the session in the browser, with\n * the body about to be sent. Return an object to add or override fields\n * (`external_order_id`, `notes`, anything your API accepts); throwing\n * cancels the checkout and reports the message via `onError`.\n */\n onBeforeCreateOrder?: CheckoutBeforeCreateOrderHandler;\n\n /**\n * Called with the created session (token, intent, expiry...) when this\n * button created it in the browser. Not called when a `session-token`\n * attribute is set, because that session was made on your server.\n */\n onOrderCreated?: (session: CheckoutSession) => void;\n\n /**\n * Order lines as data. The `items` attribute carries the same as JSON, for\n * HTML templates that have no way to set a property.\n */\n items: CheckoutItem[] | null = null;\n\n private client: EsaalatCheckout | null = null;\n private clientKey: string | null = null;\n private button: HTMLButtonElement | null = null;\n private busy = false;\n private watchTimer: ReturnType<typeof setInterval> | null = null;\n /** Text written between the tags, captured before the button is injected. */\n private slotLabel: string | null = null;\n\n connectedCallback(): void {\n this.render();\n }\n\n disconnectedCallback(): void {\n // The checkout itself lives on `document.body`, so a removed button must\n // not cancel a payment in progress. Only the state watcher goes away.\n this.stopWatch();\n }\n\n attributeChangedCallback(\n name: string,\n previous: string | null,\n value: string | null\n ): void {\n if (previous === value) return;\n\n if (name === \"publishable-key\") {\n // A different key means a different client; the next click builds it.\n this.client = null;\n this.clientKey = null;\n return;\n }\n if (name === \"label\" || name === \"locale\") {\n this.applyLabel();\n return;\n }\n if (name === \"disabled\") {\n this.syncBusy();\n }\n }\n\n /** Open the checkout, exactly as a click does (for programmatic use). */\n async open(): Promise<void> {\n await this.start();\n }\n\n private handleClick = (): void => {\n // Not awaited: the click task must keep running synchronously so the\n // browser-window presentation is still inside the buyer's gesture.\n void this.start();\n };\n\n private async start(): Promise<void> {\n if (this.busy || this.isCheckoutOpen()) return;\n\n const key = (this.getAttribute(\"publishable-key\") ?? \"\").trim();\n // A `session-token` already names the checkout; the key only creates one.\n if (!key && !this.attribute(\"session-token\")) {\n this.reportError(\n new EsaalatCheckoutError(\"A publishable key is required.\", \"configuration\")\n );\n return;\n }\n\n this.setBusy(true);\n this.watch();\n\n try {\n const items = this.readItems();\n const client = this.ensureClient(key);\n const result = await client.open(this.openOptions(items));\n this.handleResult(result);\n } catch (error) {\n this.reportError(asError(error));\n } finally {\n this.setBusy(false);\n }\n }\n\n private ensureClient(key: string): EsaalatCheckout {\n if (this.client && this.clientKey === key) return this.client;\n // Replacing the client only happens when the key changes. It has no open\n // checkout to lose: `start()` refuses to run while one is on screen.\n this.clientKey = key;\n this.client = new EsaalatCheckout({\n publishableKey: key,\n locale: this.locale(),\n });\n return this.client;\n }\n\n private openOptions(items: CheckoutItem[] | null): CheckoutOpenOptions {\n return {\n amount: this.attribute(\"amount\"),\n items: items ?? undefined,\n currency: this.attribute(\"currency\"),\n externalOrderId: this.attribute(\"external-order-id\"),\n notes: this.attribute(\"notes\"),\n wallet: this.attribute(\"wallet\"),\n sessionToken: this.attribute(\"session-token\"),\n portalUrl: this.attribute(\"portal-url\"),\n locale: this.locale(),\n presentation: this.presentation(),\n onBeforeCreateOrder: this.onBeforeCreateOrder,\n onOrderCreated: this.onOrderCreated,\n };\n }\n\n private handleResult(result: CheckoutResult): void {\n const outcome = OUTCOMES[result.status];\n if (!outcome) return;\n\n // The status is the single source of truth: only the matching callback\n // runs, so a merchant can wire all five without guarding each one.\n this.callSafely(this[outcome.handler] as ((r: CheckoutResult) => void) | undefined, result);\n this.dispatchOutcome(outcome.event, result);\n }\n\n private reportError(error: Error): void {\n this.callSafely(this.onError, error);\n this.dispatchOutcome(ESAALAT_CHECKOUT_EVENTS.error, error);\n }\n\n /**\n * DOM events carry the same detail as the callbacks, so templates that bind\n * events instead of properties (`@esaalat-verified`, `(esaalat-verified)`)\n * need no extra JS.\n */\n private dispatchOutcome(name: string, detail: CheckoutResult | Error): void {\n this.dispatchEvent(\n new CustomEvent(name, { detail, bubbles: true, composed: true })\n );\n }\n\n private callSafely<Arg>(handler: ((argument: Arg) => void) | undefined, argument: Arg): void {\n if (!handler) return;\n try {\n handler(argument);\n } catch {\n // A merchant callback must never break the element's own bookkeeping.\n }\n }\n\n private readItems(): CheckoutItem[] | null {\n if (this.items && this.items.length > 0) return this.items;\n\n const raw = this.attribute(\"items\");\n if (!raw) return null;\n try {\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) throw new Error(\"not an array\");\n return parsed as CheckoutItem[];\n } catch {\n throw new EsaalatCheckoutError(\n \"The items attribute must be a JSON array of order lines.\",\n \"configuration\"\n );\n }\n }\n\n private attribute(name: string): string | undefined {\n const value = (this.getAttribute(name) ?? \"\").trim();\n return value || undefined;\n }\n\n private locale(): CheckoutLocale {\n return this.getAttribute(\"locale\") === \"en\" ? \"en\" : \"ar\";\n }\n\n private presentation(): CheckoutPresentation {\n // A component implies in-page, so the modal is the default here even\n // though the imperative client opens a browser window by default.\n return this.getAttribute(\"presentation\") === \"window\" ? \"window\" : \"modal\";\n }\n\n private isCheckoutOpen(): boolean {\n return this.client?.isOpen ?? false;\n }\n\n // -- rendering -----------------------------------------------------------\n\n private render(): void {\n if (!this.button) {\n // Read any \"Pay now\" written between the tags before the button exists,\n // so `<esaalat-checkout-button>Pay</esaalat-checkout-button>` works.\n if (this.slotLabel === null) {\n this.slotLabel = (this.textContent ?? \"\").trim();\n }\n\n const button = this.ownerDocument.createElement(\"button\");\n button.type = \"button\";\n button.className = \"esaalat-checkout-button\";\n button.addEventListener(\"click\", this.handleClick);\n this.replaceChildren(button);\n this.button = button;\n this.applyStyles(button);\n }\n this.applyLabel();\n this.syncBusy();\n }\n\n private applyLabel(): void {\n if (!this.button) return;\n const label =\n this.attribute(\"label\") ??\n (this.slotLabel || undefined) ??\n DEFAULT_LABELS[this.locale()];\n this.button.textContent = label;\n }\n\n /**\n * Defaults live on the inner button and read CSS custom properties, so a\n * merchant themes the control from their own stylesheet without the element\n * shipping a global stylesheet or a shadow root that would trap their CSS.\n */\n private applyStyles(button: HTMLButtonElement): void {\n button.style.appearance = \"none\";\n button.style.border =\n \"1px solid var(--esaalat-button-border, transparent)\";\n button.style.borderRadius = \"var(--esaalat-button-radius, 12px)\";\n button.style.background = \"var(--esaalat-button-background, #1f2a24)\";\n button.style.color = \"var(--esaalat-button-color, #ffffff)\";\n button.style.font = \"inherit\";\n button.style.fontSize = \"var(--esaalat-button-font-size, 15px)\";\n button.style.fontWeight = \"600\";\n button.style.lineHeight = \"1.2\";\n button.style.padding = \"var(--esaalat-button-padding, 14px 22px)\";\n button.style.cursor = \"pointer\";\n button.style.transition = \"opacity 120ms ease-out\";\n }\n\n private setBusy(busy: boolean): void {\n this.busy = busy;\n this.syncBusy();\n }\n\n private syncBusy(): void {\n if (!this.button) return;\n const busy = this.busy || this.isCheckoutOpen();\n // `disabled` always locks the button; otherwise it is locked only while\n // this element is the one driving a checkout.\n const locked = busy || this.hasAttribute(\"disabled\");\n this.button.disabled = locked;\n this.button.setAttribute(\"aria-busy\", busy ? \"true\" : \"false\");\n this.button.style.opacity = this.hasAttribute(\"disabled\") && !busy ? \"0.6\" : \"1\";\n this.button.style.cursor = locked ? \"default\" : \"pointer\";\n }\n\n // -- state watcher -------------------------------------------------------\n\n /**\n * A result resolves `open()`, but the portal stays on screen for a moment\n * (`VERIFIED` auto-closes; every other outcome waits for the buyer to close\n * it). The button has to stay locked until then — a click in that window\n * would only reach \"a checkout is already open\".\n */\n private watch(): void {\n if (this.watchTimer !== null || typeof setInterval !== \"function\") return;\n this.watchTimer = setInterval(() => {\n // `busy` covers the window before the portal has loaded (a slow session\n // request): the checkout is not open yet, but the watch is still needed\n // for when it closes afterwards.\n if (!this.busy && !this.isCheckoutOpen()) this.stopWatch();\n this.syncBusy();\n }, WATCH_INTERVAL_MS);\n }\n\n private stopWatch(): void {\n if (this.watchTimer === null) return;\n clearInterval(this.watchTimer);\n this.watchTimer = null;\n }\n}\n\n/**\n * Define `<esaalat-checkout-button>`. Safe to call repeatedly and on the\n * server (no `customElements`), so a bundler can import this module during\n * SSR without a guard of its own.\n *\n * Returns whether this call defined the element.\n */\nexport function registerEsaalatCheckoutButton(): boolean {\n if (typeof customElements === \"undefined\") return false;\n if (customElements.get(ESAALAT_CHECKOUT_BUTTON_TAG)) return false;\n customElements.define(ESAALAT_CHECKOUT_BUTTON_TAG, EsaalatCheckoutButtonElement);\n return true;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [ESAALAT_CHECKOUT_BUTTON_TAG]: EsaalatCheckoutButtonElement;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/modal.ts","../src/window.ts","../src/client.ts","../src/element.ts"],"sourcesContent":["export type CheckoutErrorCode =\n | \"configuration\"\n | \"network\"\n | \"api\"\n | \"session\"\n | \"unavailable\"\n | \"aborted\";\n\nexport class EsaalatCheckoutError extends Error {\n readonly code: CheckoutErrorCode;\n readonly status?: number;\n readonly details?: unknown;\n\n constructor(\n message: string,\n code: CheckoutErrorCode,\n options: { status?: number; details?: unknown; cause?: unknown } = {}\n ) {\n super(message);\n this.name = \"EsaalatCheckoutError\";\n this.code = code;\n this.status = options.status;\n this.details = options.details;\n if (options.cause !== undefined) {\n // `cause` is ES2022; assigning it keeps the package ES2020-compatible.\n (this as Error & { cause?: unknown }).cause = options.cause;\n }\n }\n}\n","import type { CheckoutView } from \"./view\";\n\nexport interface CheckoutModalLabels {\n close: string;\n loading: string;\n errorTitle: string;\n}\n\ninterface CheckoutModalOptions {\n zIndex: number;\n title: string;\n labels: CheckoutModalLabels;\n onDismiss: () => void;\n}\n\nconst MODAL_CSS = `\n :host { all: initial; }\n *, *::before, *::after { box-sizing: border-box; }\n .overlay {\n position: fixed;\n inset: 0;\n z-index: 0;\n display: grid;\n place-items: center;\n padding: 12px;\n background: rgba(12, 11, 8, 0.58);\n -webkit-backdrop-filter: blur(7px);\n backdrop-filter: blur(7px);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n color: #0b0b0b;\n pointer-events: auto;\n animation: fade 180ms ease-out;\n }\n .dialog {\n position: relative;\n width: min(460px, calc(100vw - 24px));\n height: min(720px, calc(100dvh - 24px));\n overflow: hidden;\n border-radius: 22px;\n background: #fffefa;\n border: 1px solid rgba(255, 255, 255, 0.5);\n box-shadow: 0 36px 100px rgba(0, 0, 0, 0.4), 0 6px 24px rgba(0, 0, 0, 0.2);\n animation: rise 220ms cubic-bezier(0.2, 0.8, 0.2, 1);\n }\n .dialog.is-frame { background: #f3f0e8; }\n .chrome {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 14px 16px;\n border-bottom: 1px solid #e7e2d7;\n background: #fffefa;\n }\n .dialog.is-frame .chrome { display: none; }\n .mark {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n display: grid;\n place-items: center;\n background: #0b0b0b;\n color: #fff;\n font-size: 14px;\n font-weight: 800;\n flex-shrink: 0;\n }\n .chrome-title {\n font-size: 13px;\n font-weight: 700;\n line-height: 1.3;\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .close {\n width: 32px;\n height: 32px;\n display: grid;\n place-items: center;\n border: 0;\n border-radius: 9px;\n background: transparent;\n color: #716f67;\n cursor: pointer;\n flex-shrink: 0;\n }\n .close:hover { background: #f3f0e8; color: #0b0b0b; }\n .close:focus-visible { outline: 2px solid #0b0b0b; outline-offset: 2px; }\n .close svg { width: 18px; height: 18px; }\n .content {\n position: absolute;\n inset: 57px 0 0;\n overflow: hidden;\n }\n .dialog.is-frame .content { inset: 0; }\n .frame {\n display: block;\n width: 100%;\n height: 100%;\n border: 0;\n background: #f3f0e8;\n }\n .panel {\n height: 100%;\n display: grid;\n place-content: center;\n justify-items: center;\n gap: 12px;\n padding: 32px;\n text-align: center;\n }\n .spinner {\n width: 34px;\n height: 34px;\n border-radius: 50%;\n border: 2px solid #e7e2d7;\n border-top-color: #0b0b0b;\n animation: spin 900ms linear infinite;\n }\n .loading { font-size: 13px; color: #716f67; }\n .error-icon {\n width: 54px;\n height: 54px;\n border-radius: 50%;\n display: grid;\n place-items: center;\n background: #fef1ef;\n border: 1px solid #f5cfca;\n color: #b42318;\n }\n .error-icon svg { width: 25px; height: 25px; }\n .error-title { margin: 0; font-size: 17px; line-height: 1.4; }\n .error-message { margin: 0; font-size: 13px; line-height: 1.7; color: #716f67; max-width: 34ch; }\n .error-close {\n margin-top: 6px;\n min-height: 42px;\n padding: 9px 22px;\n border: 1px solid #e7e2d7;\n border-radius: 11px;\n background: transparent;\n color: #0b0b0b;\n font: inherit;\n font-size: 13px;\n font-weight: 700;\n cursor: pointer;\n }\n .error-close:hover { background: #f3f0e8; }\n .error-close:focus-visible { outline: 2px solid #0b0b0b; outline-offset: 2px; }\n @keyframes spin { to { transform: rotate(360deg); } }\n @keyframes fade { from { opacity: 0; } }\n @keyframes rise { from { opacity: 0; transform: translateY(10px) scale(0.985); } }\n @media (max-width: 520px) {\n .overlay { padding: 0; }\n .dialog {\n width: 100vw;\n height: 100dvh;\n max-height: none;\n border-radius: 0;\n border: 0;\n }\n .chrome { padding-top: calc(14px + env(safe-area-inset-top)); }\n }\n @media (prefers-color-scheme: dark) {\n .overlay { background: rgba(0, 0, 0, 0.7); }\n .dialog, .chrome { background: #1d1b17; border-color: #343028; color: #f6f2e8; }\n .dialog.is-frame, .frame { background: #141310; }\n .chrome-title { color: #f6f2e8; }\n .close { color: #aaa59a; }\n .close:hover { background: #2b2721; color: #f6f2e8; }\n .spinner { border-color: #343028; border-top-color: #f6f2e8; }\n .loading, .error-message { color: #aaa59a; }\n .error-icon { background: #2b1b19; border-color: #4b2c28; color: #f18d83; }\n .error-close { border-color: #343028; color: #f6f2e8; }\n .error-close:hover { background: #2b2721; }\n }\n @media (prefers-reduced-motion: reduce) {\n .overlay, .dialog { animation: none; }\n .spinner { animation-duration: 0.01ms; }\n }\n`;\n\nfunction element<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n className?: string\n): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n if (className) node.className = className;\n return node;\n}\n\nfunction closeSvg(): SVGSVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"1.8\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", \"M18 6 6 18M6 6l12 12\");\n svg.append(path);\n return svg;\n}\n\nfunction alertSvg(): SVGSVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"1.8\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", \"M12 9v4M12 17h.01M10.3 3.9 2.5 17.4A2 2 0 0 0 4.2 20h15.6a2 2 0 0 0 1.7-2.6L13.7 3.9a2 2 0 0 0-3.4 0Z\");\n svg.append(path);\n return svg;\n}\n\n/**\n * The modal lives in a shadow root so a merchant's global CSS cannot leak into\n * the checkout (or the other way around). The iframe is the only content once\n * the session is ready; the portal owns its own close button.\n */\nexport class CheckoutModal implements CheckoutView {\n private readonly host: HTMLDivElement;\n private readonly shadow: ShadowRoot;\n private readonly overlay: HTMLDivElement;\n private readonly dialog: HTMLDivElement;\n private readonly closeButton: HTMLButtonElement;\n private readonly content: HTMLDivElement;\n private frame: HTMLIFrameElement | null = null;\n private previousOverflow = \"\";\n private previousFocus: Element | null = null;\n private destroyed = false;\n\n onLoad: (() => void) | null = null;\n private readonly onDismiss: () => void;\n\n constructor(private readonly options: CheckoutModalOptions) {\n this.onDismiss = options.onDismiss;\n\n this.host = document.createElement(\"div\");\n this.host.setAttribute(\"data-esaalat-checkout\", \"\");\n this.host.style.cssText = `all: initial; position: fixed; inset: 0; z-index: ${options.zIndex}; pointer-events: none;`;\n\n this.shadow = this.host.attachShadow({ mode: \"open\" });\n const style = element(\"style\");\n style.textContent = MODAL_CSS;\n this.shadow.append(style);\n\n this.overlay = element(\"div\", \"overlay\");\n this.overlay.addEventListener(\"mousedown\", (event) => {\n if (event.target === this.overlay) this.onDismiss();\n });\n\n this.dialog = element(\"div\", \"dialog\");\n this.dialog.setAttribute(\"role\", \"dialog\");\n this.dialog.setAttribute(\"aria-modal\", \"true\");\n this.dialog.setAttribute(\"aria-label\", options.title);\n\n const chrome = element(\"div\", \"chrome\");\n const mark = element(\"span\", \"mark\");\n mark.textContent = \"E\";\n mark.setAttribute(\"aria-hidden\", \"true\");\n const title = element(\"span\", \"chrome-title\");\n title.textContent = options.title;\n\n this.closeButton = element(\"button\", \"close\");\n this.closeButton.type = \"button\";\n this.closeButton.setAttribute(\"aria-label\", options.labels.close);\n this.closeButton.append(closeSvg());\n this.closeButton.addEventListener(\"click\", () => this.onDismiss());\n\n chrome.append(mark, title, this.closeButton);\n\n this.content = element(\"div\", \"content\");\n this.showLoading();\n\n this.dialog.append(chrome, this.content);\n this.overlay.append(this.dialog);\n this.shadow.append(this.overlay);\n }\n\n open(): void {\n if (!document.body) {\n throw new Error(\"Esaalat checkout needs a document body.\");\n }\n this.previousOverflow = document.body.style.overflow;\n this.previousFocus = document.activeElement;\n document.body.style.overflow = \"hidden\";\n document.body.append(this.host);\n document.addEventListener(\"keydown\", this.handleKeyDown, true);\n this.closeButton.focus({ preventScroll: true });\n }\n\n load(url: string): void {\n if (this.destroyed) return;\n this.dialog.classList.add(\"is-frame\");\n this.content.replaceChildren();\n\n const frame = document.createElement(\"iframe\");\n frame.className = \"frame\";\n frame.src = url;\n frame.title = this.options.title;\n frame.setAttribute(\"allow\", \"clipboard-write\");\n frame.setAttribute(\"referrerpolicy\", \"strict-origin-when-cross-origin\");\n frame.setAttribute(\"loading\", \"eager\");\n frame.addEventListener(\"load\", () => {\n this.onLoad?.();\n try {\n frame.focus({ preventScroll: true });\n } catch {\n // focus is best-effort in embedded browsers\n }\n });\n\n this.frame = frame;\n this.content.append(frame);\n }\n\n get contentWindow(): Window | null {\n return this.frame?.contentWindow ?? null;\n }\n\n showError(message: string): void {\n if (this.destroyed) return;\n this.content.replaceChildren();\n\n const panel = element(\"div\", \"panel\");\n const icon = element(\"span\", \"error-icon\");\n icon.append(alertSvg());\n const title = element(\"h2\", \"error-title\");\n title.textContent = this.options.labels.errorTitle;\n const text = element(\"p\", \"error-message\");\n text.textContent = message;\n const close = element(\"button\", \"error-close\");\n close.type = \"button\";\n close.textContent = this.options.labels.close;\n close.addEventListener(\"click\", () => this.onDismiss());\n\n panel.append(icon, title, text, close);\n this.content.append(panel);\n this.dialog.classList.remove(\"is-frame\");\n close.focus({ preventScroll: true });\n }\n\n private showLoading(): void {\n this.content.replaceChildren();\n const panel = element(\"div\", \"panel\");\n const spinner = element(\"span\", \"spinner\");\n spinner.setAttribute(\"aria-hidden\", \"true\");\n const label = element(\"p\", \"loading\");\n label.textContent = this.options.labels.loading;\n panel.append(spinner, label);\n this.content.append(panel);\n }\n\n private handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n this.onDismiss();\n }\n };\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n document.removeEventListener(\"keydown\", this.handleKeyDown, true);\n document.body.style.overflow = this.previousOverflow;\n this.host.remove();\n if (this.previousFocus instanceof HTMLElement && this.previousFocus.isConnected) {\n try {\n this.previousFocus.focus({ preventScroll: true });\n } catch {\n // ignore\n }\n }\n this.onLoad = null;\n this.frame = null;\n }\n}\n","import type { CheckoutView } from \"./view\";\n\nexport interface CheckoutWindowOptions {\n title: string;\n labels: {\n loading: string;\n errorTitle: string;\n close: string;\n };\n dir: \"rtl\" | \"ltr\";\n lang: string;\n onDismiss: () => void;\n}\n\nconst WINDOW_NAME = \"esaalat-checkout\";\nconst WINDOW_WIDTH = 480;\nconst WINDOW_HEIGHT = 800;\nconst CLOSE_POLL_MS = 400;\n\nconst DOC_CSS = `\n * { box-sizing: border-box; }\n html, body { height: 100%; }\n body {\n margin: 0;\n display: grid;\n place-items: center;\n padding: 24px;\n background: #f3f0e8;\n color: #0b0b0b;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n }\n .panel {\n display: grid;\n justify-items: center;\n gap: 14px;\n max-width: 34ch;\n text-align: center;\n }\n .error-icon {\n width: 54px;\n height: 54px;\n border-radius: 50%;\n display: grid;\n place-items: center;\n background: #fef1ef;\n border: 1px solid #f5cfca;\n color: #b42318;\n font-size: 24px;\n font-weight: 800;\n }\n .error-title { margin: 0; font-size: 17px; line-height: 1.4; }\n .error-message { margin: 0; font-size: 13px; line-height: 1.7; color: #716f67; }\n .error-close {\n margin-top: 4px;\n min-height: 42px;\n padding: 9px 22px;\n border: 1px solid #ded7c8;\n border-radius: 11px;\n background: transparent;\n color: #0b0b0b;\n font: inherit;\n font-size: 13px;\n font-weight: 700;\n cursor: pointer;\n }\n .error-close:hover { background: #e9e4d8; }\n @media (prefers-color-scheme: dark) {\n body { background: #141310; color: #f6f2e8; }\n .error-message { color: #aaa59a; }\n .error-icon { background: #2b1b19; border-color: #4b2c28; color: #f18d83; }\n .error-close { border-color: #343028; color: #f6f2e8; }\n .error-close:hover { background: #2b2721; }\n }\n`;\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\n/** A centered popup, sized like the checkout card it replaces. */\nfunction windowFeatures(): string {\n const screenWidth = window.screen?.availWidth ?? WINDOW_WIDTH;\n const screenHeight = window.screen?.availHeight ?? WINDOW_HEIGHT;\n const width = Math.min(WINDOW_WIDTH, Math.max(320, screenWidth - 40));\n const height = Math.min(WINDOW_HEIGHT, Math.max(480, screenHeight - 40));\n const baseX = typeof window.screenX === \"number\" ? window.screenX : 0;\n const baseY = typeof window.screenY === \"number\" ? window.screenY : 0;\n const outerWidth = window.outerWidth || width;\n const outerHeight = window.outerHeight || height;\n const left = Math.max(0, Math.round(baseX + (outerWidth - width) / 2));\n const top = Math.max(0, Math.round(baseY + (outerHeight - height) / 2));\n\n return [\n \"popup=yes\",\n `width=${width}`,\n `height=${height}`,\n `left=${left}`,\n `top=${top}`,\n \"resizable=yes\",\n \"scrollbars=yes\",\n ].join(\",\");\n}\n\nfunction documentHtml(\n title: string,\n dir: \"rtl\" | \"ltr\",\n lang: string,\n body: string\n): string {\n return [\n \"<!doctype html>\",\n `<html dir=\"${dir}\" lang=\"${lang}\">`,\n \"<head>\",\n '<meta charset=\"utf-8\" />',\n '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />',\n '<meta name=\"robots\" content=\"noindex\" />',\n `<title>${escapeHtml(title)}</title>`,\n `<style>${DOC_CSS}</style>`,\n \"</head>\",\n `<body>${body}</body>`,\n \"</html>\",\n ].join(\"\");\n}\n\n/**\n * Opens the hosted checkout in its own browser window.\n *\n * The window has to be requested synchronously from the buyer's click, before\n * the session request, or every popup blocker swallows it — so the constructor\n * opens a blank window with a \"preparing checkout\" page and `load()` navigates\n * it once the session exists.\n *\n * The merchant page keeps talking to the portal with `postMessage`: the window\n * handle stays valid across the navigation, and the portal answers the opener\n * (see `createEmbeddedBridge`).\n */\nexport class CheckoutWindow implements CheckoutView {\n private readonly win: Window;\n private readonly onDismiss: () => void;\n private readonly dir: \"rtl\" | \"ltr\";\n private readonly lang: string;\n private readonly title: string;\n private readonly labels: CheckoutWindowOptions[\"labels\"];\n private pollId: number | null = null;\n private navigated = false;\n private destroyed = false;\n\n onLoad: (() => void) | null = null;\n\n constructor(options: CheckoutWindowOptions) {\n const opened = window.open(\"\", WINDOW_NAME, windowFeatures());\n if (!opened) {\n throw new Error(\"The browser blocked the checkout window.\");\n }\n\n this.win = opened;\n this.onDismiss = options.onDismiss;\n this.title = options.title;\n this.labels = options.labels;\n this.dir = options.dir;\n this.lang = options.lang;\n\n this.pollId = window.setInterval(() => this.checkClosed(), CLOSE_POLL_MS);\n\n try {\n this.win.focus();\n } catch {\n // focus is best-effort in embedded browsers\n }\n }\n\n get contentWindow(): Window | null {\n return this.win;\n }\n\n open(): void {\n try {\n this.win.focus();\n } catch {\n // focus is best-effort\n }\n }\n\n load(url: string): void {\n if (this.destroyed) return;\n this.navigated = true;\n try {\n // `replace` keeps the empty window out of the buyer's back history.\n this.win.location.replace(url);\n } catch {\n if (this.win.closed) {\n this.dismiss();\n return;\n }\n // Some embedded browsers refuse one navigation call but accept another.\n try {\n this.win.location.href = url;\n } catch {\n // The portal never loaded; the close poll will notice if it is gone.\n }\n }\n this.onLoad?.();\n }\n\n showError(message: string): void {\n // After the navigation the portal owns that document; nothing safe to paint.\n if (this.destroyed || this.navigated) return;\n\n this.renderError(\n documentHtml(\n this.title,\n this.dir,\n this.lang,\n `<div class=\"panel\">` +\n `<span class=\"error-icon\" aria-hidden=\"true\">!</span>` +\n `<h2 class=\"error-title\">${escapeHtml(this.labels.errorTitle)}</h2>` +\n `<p class=\"error-message\">${escapeHtml(message)}</p>` +\n `<button class=\"error-close\" type=\"button\">${escapeHtml(this.labels.close)}</button>` +\n `</div>`\n )\n );\n\n try {\n const close = this.win.document.querySelector(\".error-close\");\n close?.addEventListener(\"click\", () => this.onDismiss());\n } catch {\n // The window went away before the close button could be wired.\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.stopPolling();\n this.onLoad = null;\n try {\n this.win.close();\n } catch {\n // Already closed by the buyer.\n }\n }\n\n /**\n * Best-effort: the placeholder document is cosmetic. A refused write must\n * never cancel the checkout — the navigation below still has to happen.\n */\n private renderError(html: string): void {\n try {\n const doc = this.win.document;\n doc.open();\n doc.write(html);\n doc.close();\n } catch {\n // Browser refused to let us paint into the blank window.\n }\n }\n\n private checkClosed(): void {\n if (this.destroyed) {\n this.stopPolling();\n return;\n }\n if (this.win.closed) this.dismiss();\n }\n\n private dismiss(): void {\n if (this.destroyed) return;\n this.stopPolling();\n this.onDismiss();\n }\n\n private stopPolling(): void {\n if (this.pollId !== null) {\n window.clearInterval(this.pollId);\n this.pollId = null;\n }\n }\n}\n","import { EsaalatCheckoutError } from \"./errors\";\nimport { CheckoutModal } from \"./modal\";\nimport type {\n CheckoutBeforeCreateOrderHandler,\n CheckoutCreatePayload,\n CheckoutItem,\n CheckoutLocale,\n CheckoutOpenOptions,\n CheckoutPresentation,\n CheckoutResult,\n CheckoutResultReason,\n CheckoutResultStatus,\n CheckoutSession,\n EsaalatCheckoutOptions,\n} from \"./types\";\nimport type { CheckoutView } from \"./view\";\nimport { CheckoutWindow } from \"./window\";\n\nconst DEFAULT_API_BASE = \"https://api.esaalat.com/api/v1\";\nconst DEFAULT_PORTAL_BASE = \"https://pay.esaalat.com\";\nconst SDK_VERSION = \"0.1.0\";\nconst REQUEST_TIMEOUT_MS = 20_000;\nconst INIT_RETRY_MS = 300;\n// A browser window needs longer than an iframe: the init message races the\n// navigation, so keep knocking until the portal answers `ready`.\nconst INIT_ATTEMPTS = 100;\nconst VERIFIED_CLOSE_MS = 1_800;\nconst ERROR_CLOSE_MS = 6_000;\n\nconst RESULT_STATUSES: CheckoutResultStatus[] = [\n \"VERIFIED\",\n \"WRONG_AMOUNT\",\n \"EXPIRED\",\n \"CANCELLED\",\n \"FAILED\",\n];\n\nconst RESULT_REASONS: CheckoutResultReason[] = [\n \"dismissed\",\n \"destroyed\",\n \"intent_cancelled\",\n \"session_expired\",\n \"session_not_found\",\n \"network_error\",\n];\n\ninterface ActiveCheckout {\n token: string | null;\n locale: CheckoutLocale;\n controller: AbortController;\n view: CheckoutView;\n settled: boolean;\n resolve: (result: CheckoutResult) => void;\n reject: (error: Error) => void;\n onResult?: (result: CheckoutResult) => void;\n}\n\ninterface PortalMessage {\n source?: unknown;\n type?: unknown;\n sessionToken?: unknown;\n payload?: unknown;\n}\n\ninterface PortalResultPayload {\n status?: unknown;\n reason?: unknown;\n intentCode?: unknown;\n amount?: unknown;\n paidAmount?: unknown;\n currency?: unknown;\n externalOrderId?: unknown;\n merchantName?: unknown;\n}\n\nfunction normalizeBase(value: string, fallback: string): string {\n const raw = value.trim() || fallback;\n let url: URL;\n try {\n const base =\n typeof window !== \"undefined\" ? window.location?.href : undefined;\n url = new URL(raw, base);\n } catch {\n throw new EsaalatCheckoutError(\n `Invalid URL: ${raw}`,\n \"configuration\"\n );\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new EsaalatCheckoutError(\n `Unsupported URL protocol: ${url.protocol}`,\n \"configuration\"\n );\n }\n return url.toString().replace(/\\/+$/, \"\");\n}\n\nfunction requestId(): string {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n // UUID v4 fallback for older embedded browsers.\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (char) => {\n const random = (Math.random() * 16) | 0;\n const value = char === \"x\" ? random : (random & 0x3) | 0x8;\n return value.toString(16);\n });\n}\n\nfunction stringOr(value: unknown, fallback = \"\"): string {\n return typeof value === \"string\" ? value : fallback;\n}\n\nfunction nullOrString(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction errorDetail(body: unknown): string | null {\n if (!body || typeof body !== \"object\") return null;\n const record = body as Record<string, unknown>;\n if (typeof record.detail === \"string\") return record.detail;\n if (Array.isArray(record.errors)) {\n for (const error of record.errors) {\n if (error && typeof error === \"object\") {\n const detail = (error as Record<string, unknown>).detail;\n if (typeof detail === \"string\") return detail;\n }\n }\n }\n for (const value of Object.values(record)) {\n if (typeof value === \"string\") return value;\n if (Array.isArray(value) && typeof value[0] === \"string\") return value[0];\n }\n return null;\n}\n\nfunction isCheckoutSession(value: unknown): value is CheckoutSession {\n if (!value || typeof value !== \"object\") return false;\n const record = value as Record<string, unknown>;\n return (\n typeof record.session_token === \"string\" &&\n typeof record.portal_url === \"string\" &&\n typeof record.amount === \"string\" &&\n typeof record.currency === \"string\"\n );\n}\n\nfunction cancelledResult(\n token: string | null,\n reason: \"dismissed\" | \"destroyed\"\n): CheckoutResult {\n return {\n status: \"CANCELLED\",\n reason,\n sessionToken: token ?? \"\",\n intentCode: null,\n amount: \"0.00\",\n paidAmount: null,\n currency: \"YER\",\n externalOrderId: \"\",\n merchantName: \"\",\n };\n}\n\n/**\n * Framework-agnostic Esaalat checkout client.\n *\n * It creates a checkout session with the merchant's publishable key, opens the\n * Esaalat-hosted portal in its own browser window (or an in-page modal when\n * asked, or when the browser blocks the window), and resolves `open()` with a\n * terminal result. The publishable key is public by design; keep the client\n * secret and any order confirmation on the server.\n */\nexport class EsaalatCheckout {\n private readonly publishableKey: string;\n private readonly apiBaseUrl: string;\n private readonly portalBaseUrl: string;\n private readonly zIndex: number;\n private readonly presentation: CheckoutPresentation;\n private readonly locale: CheckoutLocale;\n private readonly fetchImpl: typeof fetch | null;\n private readonly defaultOnResult?: (result: CheckoutResult) => void;\n private readonly defaultOnError?: (error: Error) => void;\n\n private active: ActiveCheckout | null = null;\n private view: CheckoutView | null = null;\n private portalOrigin: string | null = null;\n private sessionToken: string | null = null;\n private initTimer: number | null = null;\n private verifiedTimer: number | null = null;\n private errorTimer: number | null = null;\n\n constructor(options: EsaalatCheckoutOptions) {\n // The key is only needed to create a session in the browser. A merchant\n // that opens a server-created session passes its token instead, so an\n // empty key is allowed here and refused by `open()` only on the create\n // path.\n const key =\n typeof options?.publishableKey === \"string\"\n ? options.publishableKey.trim()\n : \"\";\n\n this.publishableKey = key;\n this.locale =\n options.locale === \"en\" || options.locale === \"ar\" ? options.locale : \"ar\";\n this.apiBaseUrl = normalizeBase(options.apiBaseUrl ?? \"\", DEFAULT_API_BASE);\n this.portalBaseUrl = normalizeBase(\n options.portalBaseUrl ?? \"\",\n DEFAULT_PORTAL_BASE\n );\n this.zIndex =\n typeof options.zIndex === \"number\" && Number.isFinite(options.zIndex)\n ? options.zIndex\n : 2_147_483_000;\n this.presentation =\n options.presentation === \"modal\" ? \"modal\" : \"window\";\n\n const fetchFromOptions = options.fetch;\n const globalFetch =\n typeof fetch === \"function\" ? fetch.bind(globalThis) : null;\n this.fetchImpl = fetchFromOptions ?? globalFetch;\n this.defaultOnResult = options.onResult;\n this.defaultOnError = options.onError;\n }\n\n /** True while a checkout window or modal is on screen. */\n get isOpen(): boolean {\n return this.view !== null;\n }\n\n /**\n * Open the hosted checkout and resolve with its terminal result.\n *\n * A second call while a checkout is open rejects; close the first one with\n * `close()` or wait for its result.\n */\n async open(options: CheckoutOpenOptions = {}): Promise<CheckoutResult> {\n if (this.active || this.view) {\n throw new EsaalatCheckoutError(\n \"A checkout is already open. Close it before starting another.\",\n \"configuration\"\n );\n }\n if (!this.fetchImpl) {\n throw new EsaalatCheckoutError(\n \"This browser does not support fetch. Use the SDK on a modern browser.\",\n \"configuration\"\n );\n }\n\n const locale =\n options.locale === \"en\" || options.locale === \"ar\"\n ? options.locale\n : this.locale;\n const items = options.items ?? [];\n const existingToken = options.sessionToken?.trim() || null;\n const hasAmount =\n options.amount !== undefined &&\n options.amount !== null &&\n String(options.amount).trim() !== \"\";\n if (!existingToken && !this.publishableKey) {\n throw new EsaalatCheckoutError(\n \"A publishable key is required to create a session. Pass one, or open a server-created `sessionToken`.\",\n \"configuration\"\n );\n }\n if (!existingToken && !hasAmount && items.length === 0) {\n throw new EsaalatCheckoutError(\n \"Provide an amount, items, or a server-created session token.\",\n \"configuration\"\n );\n }\n if (!existingToken && items.length > 0) {\n for (const item of items) {\n if (!item.name || item.price === undefined || item.price === null) {\n throw new EsaalatCheckoutError(\n \"Every item needs a name and a price.\",\n \"configuration\"\n );\n }\n }\n }\n\n const labels =\n locale === \"ar\"\n ? {\n close: \"إغلاق\",\n loading: \"جارٍ تجهيز الدفع الآمن…\",\n errorTitle: \"تعذّر بدء الدفع\",\n }\n : {\n close: \"Close\",\n loading: \"Preparing secure checkout…\",\n errorTitle: \"Couldn't start the checkout\",\n };\n\n const presentation: CheckoutPresentation =\n options.presentation === \"window\" || options.presentation === \"modal\"\n ? options.presentation\n : this.presentation;\n\n // The view is created before the first `await`: a browser window has to be\n // requested inside the buyer's click, or popup blockers discard it.\n let view: CheckoutView;\n try {\n view = this.createView(presentation, labels, locale);\n view.open();\n } catch (error) {\n throw new EsaalatCheckoutError(\n \"The checkout could not be opened.\",\n \"unavailable\",\n { cause: error }\n );\n }\n\n const controller = new AbortController();\n let resolvePromise!: (result: CheckoutResult) => void;\n let rejectPromise!: (error: Error) => void;\n const promise = new Promise<CheckoutResult>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n });\n\n const onResult = options.onResult ?? this.defaultOnResult;\n const onError = options.onError ?? this.defaultOnError;\n\n const active: ActiveCheckout = {\n token: null,\n locale,\n controller,\n view,\n settled: false,\n resolve: resolvePromise,\n reject: rejectPromise,\n onResult,\n };\n this.active = active;\n this.view = view;\n this.sessionToken = null;\n this.portalOrigin = null;\n\n view.onLoad = () => this.startInitRetry();\n\n let portalUrl: string;\n try {\n if (existingToken) {\n active.token = existingToken;\n this.sessionToken = existingToken;\n portalUrl = this.buildPortalUrl(\n existingToken,\n options.portalUrl ?? \"\",\n locale\n );\n } else {\n const session = await this.createSession(\n options,\n locale,\n controller.signal\n );\n // The buyer closed the checkout while the session was being created.\n if (active.settled) return promise;\n active.token = session.session_token;\n this.sessionToken = session.session_token;\n portalUrl = this.buildPortalUrl(\n session.session_token,\n session.portal_url,\n locale\n );\n }\n this.portalOrigin = new URL(portalUrl).origin;\n } catch (error) {\n if (active.settled) return promise;\n const wrapped =\n error instanceof EsaalatCheckoutError\n ? error\n : new EsaalatCheckoutError(\n \"Esaalat returned an invalid checkout URL.\",\n \"session\",\n { cause: error }\n );\n active.settled = true;\n this.active = null;\n this.removeMessageListener();\n try {\n onError?.(wrapped);\n } catch {\n // A merchant callback must not prevent the promise from settling.\n }\n active.reject(wrapped);\n view.showError(wrapped.message);\n this.errorTimer = window.setTimeout(() => {\n if (this.view === view) this.teardown();\n }, ERROR_CLOSE_MS);\n return promise;\n }\n\n window.addEventListener(\"message\", this.handleMessage);\n view.load(portalUrl);\n return promise;\n }\n\n /** Close the checkout. An in-flight `open()` resolves with CANCELLED. */\n close(): void {\n if (this.active) {\n this.dismiss();\n return;\n }\n this.teardown();\n }\n\n /** Remove the checkout view and any listeners without resolving a result. */\n destroy(): void {\n if (this.active && !this.active.settled) {\n this.finish(cancelledResult(this.sessionToken, \"destroyed\"));\n return;\n }\n this.teardown();\n }\n\n private createView(\n presentation: CheckoutPresentation,\n labels: { close: string; loading: string; errorTitle: string },\n locale: CheckoutLocale\n ): CheckoutView {\n const title =\n locale === \"ar\" ? \"إيصالات — دفع آمن\" : \"Esaalat — Secure checkout\";\n const onDismiss = () => this.dismiss();\n\n if (presentation === \"window\") {\n try {\n return new CheckoutWindow({\n title,\n labels,\n dir: locale === \"ar\" ? \"rtl\" : \"ltr\",\n lang: locale,\n onDismiss,\n });\n } catch {\n // The popup was blocked (or there is no window): the modal is the\n // always-available fallback, so the buyer still gets to pay.\n }\n }\n\n return new CheckoutModal({\n zIndex: this.zIndex,\n title,\n labels,\n onDismiss,\n });\n }\n\n private buildPortalUrl(\n sessionToken: string,\n rawPortalUrl: string,\n locale: CheckoutLocale\n ): string {\n const raw =\n rawPortalUrl.trim() ||\n `${this.portalBaseUrl}/checkout/${encodeURIComponent(sessionToken)}`;\n const url = new URL(raw);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new Error(\"Unsupported portal protocol\");\n }\n url.searchParams.set(\"lang\", locale);\n return url.toString();\n }\n\n private async createSession(\n options: CheckoutOpenOptions,\n locale: CheckoutLocale,\n outerSignal: AbortSignal\n ): Promise<CheckoutSession> {\n if (!this.fetchImpl) {\n throw new EsaalatCheckoutError(\"fetch is unavailable\", \"configuration\");\n }\n\n let payload: CheckoutCreatePayload = {};\n if (options.amount !== undefined && options.amount !== null) {\n payload.amount = String(options.amount);\n }\n if (options.items?.length) {\n payload.items = options.items.map((item: CheckoutItem) => ({\n name: item.name,\n ...(item.description ? { description: item.description } : {}),\n price: String(item.price),\n quantity: item.quantity ?? 1,\n }));\n }\n if (options.currency) payload.currency = options.currency;\n if (options.externalOrderId) {\n payload.external_order_id = options.externalOrderId;\n }\n if (options.notes) payload.notes = options.notes;\n if (options.wallet) payload.wallet = options.wallet;\n\n // The merchant's last word on what is sent. Whatever this throws becomes\n // the checkout's own error, so a veto reaches `open()` as `configuration`\n // with the merchant's message instead of being swallowed.\n const beforeCreate: CheckoutBeforeCreateOrderHandler | undefined =\n options.onBeforeCreateOrder;\n if (beforeCreate) {\n let updated: CheckoutCreatePayload | void;\n try {\n updated = await beforeCreate(payload);\n } catch (error) {\n throw new EsaalatCheckoutError(\n error instanceof Error && error.message\n ? error.message\n : locale === \"ar\"\n ? \"أُلغي الدفع.\"\n : \"The checkout was cancelled.\",\n \"configuration\",\n { cause: error }\n );\n }\n if (updated && typeof updated === \"object\") payload = updated;\n }\n\n const controller = new AbortController();\n let timedOut = false;\n const timeout = window.setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, REQUEST_TIMEOUT_MS);\n const abortOuter = () => controller.abort();\n outerSignal.addEventListener(\"abort\", abortOuter);\n\n try {\n const response = await this.fetchImpl(\n `${this.apiBaseUrl}/checkout/sdk/sessions/`,\n {\n method: \"POST\",\n credentials: \"omit\",\n cache: \"no-store\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n \"ESAALAT-PUBLISHABLE-KEY\": this.publishableKey,\n \"ESAALAT-IDEMPOTENCY-KEY\":\n options.idempotencyKey?.trim() || requestId(),\n \"ESAALAT-SDK-VERSION\": SDK_VERSION,\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n }\n );\n\n const session: unknown = await response.json().catch(() => null);\n if (!response.ok) {\n throw new EsaalatCheckoutError(\n errorDetail(session) ||\n (locale === \"ar\"\n ? \"تعذّر إنشاء جلسة الدفع.\"\n : \"Couldn't create the checkout session.\"),\n \"api\",\n { status: response.status, details: session }\n );\n }\n if (!isCheckoutSession(session)) {\n throw new EsaalatCheckoutError(\n \"Esaalat returned an invalid checkout session.\",\n \"session\",\n { details: session }\n );\n }\n\n // The session exists; a broken listener must not kill the payment.\n try {\n options.onOrderCreated?.(session);\n } catch {\n // Ignored on purpose.\n }\n\n return session;\n } catch (error) {\n if (error instanceof EsaalatCheckoutError) throw error;\n if (timedOut) {\n throw new EsaalatCheckoutError(\n locale === \"ar\"\n ? \"انتهت مهلة الاتصال بإيصالات. حاول مرة أخرى.\"\n : \"The connection to Esaalat timed out. Please try again.\",\n \"network\",\n { cause: error }\n );\n }\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw error;\n }\n throw new EsaalatCheckoutError(\n locale === \"ar\"\n ? \"تعذّر الاتصال بإيصالات. تحقق من اتصالك وحاول مرة أخرى.\"\n : \"Couldn't reach Esaalat. Check your connection and try again.\",\n \"network\",\n { cause: error }\n );\n } finally {\n window.clearTimeout(timeout);\n outerSignal.removeEventListener(\"abort\", abortOuter);\n }\n }\n\n private startInitRetry(): void {\n this.clearInitTimer();\n let attempts = 0;\n\n const tick = () => {\n if (!this.view || !this.portalOrigin || !this.sessionToken) return;\n this.postInit();\n attempts += 1;\n if (attempts < INIT_ATTEMPTS) {\n this.initTimer = window.setTimeout(tick, INIT_RETRY_MS);\n } else {\n this.initTimer = null;\n }\n };\n\n tick();\n }\n\n private postInit(): void {\n const target = this.view?.contentWindow;\n if (!target || !this.portalOrigin || !this.sessionToken) return;\n const message = {\n source: \"esaalat-checkout-sdk\",\n version: 1,\n type: \"init\",\n sessionToken: this.sessionToken,\n parentOrigin: window.location.origin,\n locale: this.active?.locale ?? this.locale,\n };\n try {\n target.postMessage(message, this.portalOrigin);\n } catch {\n // The iframe may have been torn down between the check and the post.\n }\n }\n\n private clearInitTimer(): void {\n if (this.initTimer !== null) {\n window.clearTimeout(this.initTimer);\n this.initTimer = null;\n }\n }\n\n private handleMessage = (event: MessageEvent): void => {\n if (!this.view || !this.portalOrigin) return;\n if (event.source !== this.view.contentWindow) return;\n if (event.origin !== this.portalOrigin) return;\n\n const data = event.data as PortalMessage | null;\n if (!data || typeof data !== \"object\") return;\n if (data.source !== \"esaalat-checkout\") return;\n if (data.sessionToken !== this.sessionToken) return;\n\n if (data.type === \"ready\") {\n this.clearInitTimer();\n return;\n }\n\n if (data.type === \"close\") {\n this.dismiss();\n return;\n }\n\n if (data.type === \"result\") {\n const result = this.parseResult(data.payload);\n if (result) this.finish(result);\n }\n };\n\n private parseResult(payload: unknown): CheckoutResult | null {\n if (!payload || typeof payload !== \"object\") return null;\n const value = payload as PortalResultPayload;\n if (\n typeof value.status !== \"string\" ||\n !RESULT_STATUSES.includes(value.status as CheckoutResultStatus)\n ) {\n return null;\n }\n\n const reason =\n typeof value.reason === \"string\" &&\n RESULT_REASONS.includes(value.reason as CheckoutResultReason)\n ? (value.reason as CheckoutResultReason)\n : undefined;\n\n return {\n status: value.status as CheckoutResultStatus,\n ...(reason ? { reason } : {}),\n sessionToken: this.sessionToken ?? \"\",\n intentCode: nullOrString(value.intentCode),\n amount: stringOr(value.amount, \"0.00\"),\n paidAmount: nullOrString(value.paidAmount),\n currency: stringOr(value.currency, \"YER\"),\n externalOrderId: stringOr(value.externalOrderId),\n merchantName: stringOr(value.merchantName),\n };\n }\n\n private finish(result: CheckoutResult): void {\n const active = this.active;\n if (!active || active.settled) return;\n\n active.settled = true;\n this.active = null;\n this.clearInitTimer();\n active.controller.abort();\n try {\n active.onResult?.(result);\n } catch {\n // A merchant callback must not prevent the promise from settling.\n }\n active.resolve(result);\n\n if (result.reason === \"dismissed\" || result.reason === \"destroyed\") {\n this.teardown();\n return;\n }\n\n if (result.status === \"VERIFIED\") {\n this.verifiedTimer = window.setTimeout(() => this.teardown(), VERIFIED_CLOSE_MS);\n }\n // Other terminal states stay visible until the buyer closes them, so the\n // reason (wrong amount, expiry, cancellation) is not flashed away.\n }\n\n private dismiss(): void {\n if (this.active && !this.active.settled) {\n this.finish(cancelledResult(this.sessionToken, \"dismissed\"));\n return;\n }\n this.teardown();\n }\n\n private removeMessageListener(): void {\n window.removeEventListener(\"message\", this.handleMessage);\n }\n\n private clearTimers(): void {\n this.clearInitTimer();\n if (this.verifiedTimer !== null) {\n window.clearTimeout(this.verifiedTimer);\n this.verifiedTimer = null;\n }\n if (this.errorTimer !== null) {\n window.clearTimeout(this.errorTimer);\n this.errorTimer = null;\n }\n }\n\n private teardown(): void {\n this.clearTimers();\n this.removeMessageListener();\n if (this.view) {\n this.view.destroy();\n this.view = null;\n }\n this.portalOrigin = null;\n this.sessionToken = null;\n this.active = null;\n }\n}\n","import { EsaalatCheckout } from \"./client\";\nimport { EsaalatCheckoutError } from \"./errors\";\nimport type {\n CheckoutBeforeCreateOrderHandler,\n CheckoutItem,\n CheckoutLocale,\n CheckoutOpenOptions,\n CheckoutPresentation,\n CheckoutResult,\n CheckoutResultStatus,\n CheckoutSession,\n} from \"./types\";\n\n/**\n * A \"Pay with Esaalat\" button that any framework can render.\n *\n * It is a custom element, not a React/Vue/Angular component, because the\n * checkout is one behaviour that should not be reimplemented per framework:\n * the same tag and the same attributes work in plain HTML, in a Vue template\n * (`@esaalat-verified`), in an Angular template (`(esaalat-verified)` with\n * `CUSTOM_ELEMENTS_SCHEMA`) and — through `esaalat-react`, which only sets\n * properties and listeners — in JSX.\n *\n * The element is a thin shell over `EsaalatCheckout`: a click calls `open()`\n * with the attributes as options, and the terminal result is routed to ONE\n * named callback per outcome (see `OUTCOMES`). Nothing here re-implements the\n * portal, the session API or the result contract.\n *\n * ```html\n * <esaalat-checkout-button\n * publishable-key=\"pk_live_...\"\n * amount=\"5000.00\"\n * external-order-id=\"order-123\"\n * ></esaalat-checkout-button>\n * <script>\n * const button = document.querySelector(\"esaalat-checkout-button\");\n * button.onVerified = (result) => console.log(result.intentCode);\n * button.onCancelled = () => console.log(\"not this time\");\n * </script>\n * ```\n */\n\n/** The tag this element is registered under. */\nexport const ESAALAT_CHECKOUT_BUTTON_TAG = \"esaalat-checkout-button\";\n\n/** Label shown when the merchant passes neither `label` nor child text. */\nconst DEFAULT_LABELS: Record<CheckoutLocale, string> = {\n ar: \"ادفع الآن\",\n en: \"Pay now\",\n};\n\ntype HandlerName =\n | \"onVerified\"\n | \"onCancelled\"\n | \"onWrongAmount\"\n | \"onExpired\"\n | \"onFailed\";\n\n/**\n * One callback per terminal status: the buyer's outcome picks exactly one row,\n * so a merchant never has to switch on `result.status` to find the interesting\n * case. `FAILED` is a result (the portal could not load a valid session), not a\n * thrown error — `onError` stays reserved for `open()` rejecting.\n */\nconst OUTCOMES: Record<\n CheckoutResultStatus,\n { handler: HandlerName; event: string }\n> = {\n VERIFIED: { handler: \"onVerified\", event: \"esaalat-verified\" },\n CANCELLED: { handler: \"onCancelled\", event: \"esaalat-cancelled\" },\n WRONG_AMOUNT: { handler: \"onWrongAmount\", event: \"esaalat-wrong-amount\" },\n EXPIRED: { handler: \"onExpired\", event: \"esaalat-expired\" },\n FAILED: { handler: \"onFailed\", event: \"esaalat-failed\" },\n};\n\n/** Names of the DOM events, exported for `addEventListener` users. */\nexport const ESAALAT_CHECKOUT_EVENTS = {\n verified: \"esaalat-verified\",\n cancelled: \"esaalat-cancelled\",\n wrongAmount: \"esaalat-wrong-amount\",\n expired: \"esaalat-expired\",\n failed: \"esaalat-failed\",\n error: \"esaalat-error\",\n} as const;\n\n/** How often the button re-checks whether its checkout has been closed. */\nconst WATCH_INTERVAL_MS = 300;\n\nfunction asError(error: unknown): Error {\n if (error instanceof Error) return error;\n return new EsaalatCheckoutError(String(error) || \"The checkout failed.\", \"unavailable\");\n}\n\n/**\n * `HTMLElement` where it exists, an empty base where it does not.\n *\n * A custom element class cannot be declared against a global that Node does\n * not have, and this module has to be importable during server rendering:\n * Next renders client components on the server, so a static import of\n * `esaalat-react` would otherwise throw `HTMLElement is not defined` before\n * the browser ever gets the module. Nothing on the server instantiates the\n * class, so the empty base is never used — `registerEsaalatCheckoutButton`\n * stays a no-op without `customElements`.\n */\nconst HTMLElementBase: typeof HTMLElement =\n typeof HTMLElement === \"undefined\"\n ? (class {} as unknown as typeof HTMLElement)\n : HTMLElement;\n\nexport class EsaalatCheckoutButtonElement extends HTMLElementBase {\n static get observedAttributes(): string[] {\n return [\n \"publishable-key\",\n \"amount\",\n \"currency\",\n \"external-order-id\",\n \"notes\",\n \"wallet\",\n \"locale\",\n \"presentation\",\n \"session-token\",\n \"portal-url\",\n \"label\",\n \"disabled\",\n \"items\",\n ];\n }\n\n /** Called with the result when the wallet alert verified the payment. */\n onVerified?: (result: CheckoutResult) => void;\n /** Called when the buyer dismissed the checkout, or the intent was cancelled. */\n onCancelled?: (result: CheckoutResult) => void;\n /** Called when a payment matched but for a different amount. */\n onWrongAmount?: (result: CheckoutResult) => void;\n /** Called when the buyer ran out of time. */\n onExpired?: (result: CheckoutResult) => void;\n /** Called when the portal could not load a valid session. */\n onFailed?: (result: CheckoutResult) => void;\n /** Called when `open()` rejects (configuration, network, API or unavailable). */\n onError?: (error: Error) => void;\n\n /**\n * Called just before this button creates the session in the browser, with\n * the body about to be sent. Return an object to add or override fields\n * (`external_order_id`, `notes`, anything your API accepts); throwing\n * cancels the checkout and reports the message via `onError`.\n */\n onBeforeCreateOrder?: CheckoutBeforeCreateOrderHandler;\n\n /**\n * Called with the created session (token, intent, expiry...) when this\n * button created it in the browser. Not called when a `session-token`\n * attribute is set, because that session was made on your server.\n */\n onOrderCreated?: (session: CheckoutSession) => void;\n\n /**\n * Order lines as data. The `items` attribute carries the same as JSON, for\n * HTML templates that have no way to set a property.\n */\n items: CheckoutItem[] | null = null;\n\n private client: EsaalatCheckout | null = null;\n private clientKey: string | null = null;\n private button: HTMLButtonElement | null = null;\n private busy = false;\n private watchTimer: ReturnType<typeof setInterval> | null = null;\n /** Text written between the tags, captured before the button is injected. */\n private slotLabel: string | null = null;\n\n connectedCallback(): void {\n this.render();\n }\n\n disconnectedCallback(): void {\n // The checkout itself lives on `document.body`, so a removed button must\n // not cancel a payment in progress. Only the state watcher goes away.\n this.stopWatch();\n }\n\n attributeChangedCallback(\n name: string,\n previous: string | null,\n value: string | null\n ): void {\n if (previous === value) return;\n\n if (name === \"publishable-key\") {\n // A different key means a different client; the next click builds it.\n this.client = null;\n this.clientKey = null;\n return;\n }\n if (name === \"label\" || name === \"locale\") {\n this.applyLabel();\n return;\n }\n if (name === \"disabled\") {\n this.syncBusy();\n }\n }\n\n /** Open the checkout, exactly as a click does (for programmatic use). */\n async open(): Promise<void> {\n await this.start();\n }\n\n private handleClick = (): void => {\n // Not awaited: the click task must keep running synchronously so the\n // browser-window presentation is still inside the buyer's gesture.\n void this.start();\n };\n\n private async start(): Promise<void> {\n if (this.busy || this.isCheckoutOpen()) return;\n\n const key = (this.getAttribute(\"publishable-key\") ?? \"\").trim();\n // A `session-token` already names the checkout; the key only creates one.\n if (!key && !this.attribute(\"session-token\")) {\n this.reportError(\n new EsaalatCheckoutError(\"A publishable key is required.\", \"configuration\")\n );\n return;\n }\n\n this.setBusy(true);\n this.watch();\n\n try {\n const items = this.readItems();\n const client = this.ensureClient(key);\n const result = await client.open(this.openOptions(items));\n this.handleResult(result);\n } catch (error) {\n this.reportError(asError(error));\n } finally {\n this.setBusy(false);\n }\n }\n\n private ensureClient(key: string): EsaalatCheckout {\n if (this.client && this.clientKey === key) return this.client;\n // Replacing the client only happens when the key changes. It has no open\n // checkout to lose: `start()` refuses to run while one is on screen.\n this.clientKey = key;\n this.client = new EsaalatCheckout({\n publishableKey: key,\n locale: this.locale(),\n });\n return this.client;\n }\n\n private openOptions(items: CheckoutItem[] | null): CheckoutOpenOptions {\n return {\n amount: this.attribute(\"amount\"),\n items: items ?? undefined,\n currency: this.attribute(\"currency\"),\n externalOrderId: this.attribute(\"external-order-id\"),\n notes: this.attribute(\"notes\"),\n wallet: this.attribute(\"wallet\"),\n sessionToken: this.attribute(\"session-token\"),\n portalUrl: this.attribute(\"portal-url\"),\n locale: this.locale(),\n presentation: this.presentation(),\n onBeforeCreateOrder: this.onBeforeCreateOrder,\n onOrderCreated: this.onOrderCreated,\n };\n }\n\n private handleResult(result: CheckoutResult): void {\n const outcome = OUTCOMES[result.status];\n if (!outcome) return;\n\n // The status is the single source of truth: only the matching callback\n // runs, so a merchant can wire all five without guarding each one.\n this.callSafely(this[outcome.handler] as ((r: CheckoutResult) => void) | undefined, result);\n this.dispatchOutcome(outcome.event, result);\n }\n\n private reportError(error: Error): void {\n this.callSafely(this.onError, error);\n this.dispatchOutcome(ESAALAT_CHECKOUT_EVENTS.error, error);\n }\n\n /**\n * DOM events carry the same detail as the callbacks, so templates that bind\n * events instead of properties (`@esaalat-verified`, `(esaalat-verified)`)\n * need no extra JS.\n */\n private dispatchOutcome(name: string, detail: CheckoutResult | Error): void {\n this.dispatchEvent(\n new CustomEvent(name, { detail, bubbles: true, composed: true })\n );\n }\n\n private callSafely<Arg>(handler: ((argument: Arg) => void) | undefined, argument: Arg): void {\n if (!handler) return;\n try {\n handler(argument);\n } catch {\n // A merchant callback must never break the element's own bookkeeping.\n }\n }\n\n private readItems(): CheckoutItem[] | null {\n if (this.items && this.items.length > 0) return this.items;\n\n const raw = this.attribute(\"items\");\n if (!raw) return null;\n try {\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) throw new Error(\"not an array\");\n return parsed as CheckoutItem[];\n } catch {\n throw new EsaalatCheckoutError(\n \"The items attribute must be a JSON array of order lines.\",\n \"configuration\"\n );\n }\n }\n\n private attribute(name: string): string | undefined {\n const value = (this.getAttribute(name) ?? \"\").trim();\n return value || undefined;\n }\n\n private locale(): CheckoutLocale {\n return this.getAttribute(\"locale\") === \"en\" ? \"en\" : \"ar\";\n }\n\n private presentation(): CheckoutPresentation {\n // A component implies in-page, so the modal is the default here even\n // though the imperative client opens a browser window by default.\n return this.getAttribute(\"presentation\") === \"window\" ? \"window\" : \"modal\";\n }\n\n private isCheckoutOpen(): boolean {\n return this.client?.isOpen ?? false;\n }\n\n // -- rendering -----------------------------------------------------------\n\n private render(): void {\n if (!this.button) {\n // Read any \"Pay now\" written between the tags before the button exists,\n // so `<esaalat-checkout-button>Pay</esaalat-checkout-button>` works.\n if (this.slotLabel === null) {\n this.slotLabel = (this.textContent ?? \"\").trim();\n }\n\n const button = this.ownerDocument.createElement(\"button\");\n button.type = \"button\";\n button.className = \"esaalat-checkout-button\";\n button.addEventListener(\"click\", this.handleClick);\n this.replaceChildren(button);\n this.button = button;\n this.applyStyles(button);\n }\n this.applyLabel();\n this.syncBusy();\n }\n\n private applyLabel(): void {\n if (!this.button) return;\n const label =\n this.attribute(\"label\") ??\n (this.slotLabel || undefined) ??\n DEFAULT_LABELS[this.locale()];\n this.button.textContent = label;\n }\n\n /**\n * Defaults live on the inner button and read CSS custom properties, so a\n * merchant themes the control from their own stylesheet without the element\n * shipping a global stylesheet or a shadow root that would trap their CSS.\n */\n private applyStyles(button: HTMLButtonElement): void {\n button.style.appearance = \"none\";\n button.style.border =\n \"1px solid var(--esaalat-button-border, transparent)\";\n button.style.borderRadius = \"var(--esaalat-button-radius, 12px)\";\n button.style.background = \"var(--esaalat-button-background, #1f2a24)\";\n button.style.color = \"var(--esaalat-button-color, #ffffff)\";\n button.style.font = \"inherit\";\n button.style.fontSize = \"var(--esaalat-button-font-size, 15px)\";\n button.style.fontWeight = \"600\";\n button.style.lineHeight = \"1.2\";\n button.style.padding = \"var(--esaalat-button-padding, 14px 22px)\";\n button.style.cursor = \"pointer\";\n button.style.transition = \"opacity 120ms ease-out\";\n }\n\n private setBusy(busy: boolean): void {\n this.busy = busy;\n this.syncBusy();\n }\n\n private syncBusy(): void {\n if (!this.button) return;\n const busy = this.busy || this.isCheckoutOpen();\n // `disabled` always locks the button; otherwise it is locked only while\n // this element is the one driving a checkout.\n const locked = busy || this.hasAttribute(\"disabled\");\n this.button.disabled = locked;\n this.button.setAttribute(\"aria-busy\", busy ? \"true\" : \"false\");\n this.button.style.opacity = this.hasAttribute(\"disabled\") && !busy ? \"0.6\" : \"1\";\n this.button.style.cursor = locked ? \"default\" : \"pointer\";\n }\n\n // -- state watcher -------------------------------------------------------\n\n /**\n * A result resolves `open()`, but the portal stays on screen for a moment\n * (`VERIFIED` auto-closes; every other outcome waits for the buyer to close\n * it). The button has to stay locked until then — a click in that window\n * would only reach \"a checkout is already open\".\n */\n private watch(): void {\n if (this.watchTimer !== null || typeof setInterval !== \"function\") return;\n this.watchTimer = setInterval(() => {\n // `busy` covers the window before the portal has loaded (a slow session\n // request): the checkout is not open yet, but the watch is still needed\n // for when it closes afterwards.\n if (!this.busy && !this.isCheckoutOpen()) this.stopWatch();\n this.syncBusy();\n }, WATCH_INTERVAL_MS);\n }\n\n private stopWatch(): void {\n if (this.watchTimer === null) return;\n clearInterval(this.watchTimer);\n this.watchTimer = null;\n }\n}\n\n/**\n * Define `<esaalat-checkout-button>`. Safe to call repeatedly and on the\n * server (no `customElements`), so a bundler can import this module during\n * SSR without a guard of its own.\n *\n * Returns whether this call defined the element.\n */\nexport function registerEsaalatCheckoutButton(): boolean {\n if (typeof customElements === \"undefined\") return false;\n if (customElements.get(ESAALAT_CHECKOUT_BUTTON_TAG)) return false;\n customElements.define(ESAALAT_CHECKOUT_BUTTON_TAG, EsaalatCheckoutButtonElement);\n return true;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [ESAALAT_CHECKOUT_BUTTON_TAG]: EsaalatCheckoutButtonElement;\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "esaalat",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Accept verified wallet payments with the Esaalat hosted checkout.",
5
5
  "license": "MIT",
6
6
  "author": "Esaalat (https://esaalat.com)",