@pybara/pybara-js 0.7.0 → 0.9.0

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.
@@ -0,0 +1,229 @@
1
+ /* Pybara.js - pybara.com */
2
+ import { n as e, r as t, t as n } from "./config-9RX2E1N4.js";
3
+ //#region src/modal/lock-page-scroll.ts
4
+ var r = 0, i = 0, a = 0;
5
+ function o(e) {
6
+ e.preventDefault();
7
+ }
8
+ function s(e) {
9
+ e.preventDefault();
10
+ }
11
+ function c(e) {
12
+ e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement || [
13
+ "ArrowUp",
14
+ "ArrowDown",
15
+ "PageUp",
16
+ "PageDown",
17
+ "Home",
18
+ "End",
19
+ " "
20
+ ].includes(e.key) && e.preventDefault();
21
+ }
22
+ function l() {
23
+ window.scrollTo(i, a);
24
+ }
25
+ function u() {
26
+ r === 0 && (i = window.scrollX, a = window.scrollY, window.addEventListener("wheel", o, { passive: !1 }), window.addEventListener("touchmove", s, { passive: !1 }), window.addEventListener("keydown", c), window.addEventListener("scroll", l)), r += 1;
27
+ }
28
+ function d() {
29
+ r !== 0 && (--r, r === 0 && (window.removeEventListener("wheel", o), window.removeEventListener("touchmove", s), window.removeEventListener("keydown", c), window.removeEventListener("scroll", l)));
30
+ }
31
+ //#endregion
32
+ //#region src/modal/modal.ts
33
+ function f() {
34
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
35
+ }
36
+ var p = [
37
+ "DESTINATION_REFUSED",
38
+ "INVALID_BENEFICIARY",
39
+ "INVALID_CHECKOUT",
40
+ "NO_WALLET_AVAILABLE",
41
+ "RATE_UNAVAILABLE",
42
+ "SITE_MISMATCH"
43
+ ];
44
+ function m(e) {
45
+ return p.includes(e) ? e : "UNKNOWN";
46
+ }
47
+ var h = class extends Error {
48
+ constructor(e, t) {
49
+ super(t), this.name = "EmbeddedError", this.code = e, Object.setPrototypeOf(this, new.target.prototype);
50
+ }
51
+ };
52
+ function g(e) {
53
+ return typeof e == "object" && !!e && typeof e.type == "string" && e.type.startsWith("pybara_embedded_");
54
+ }
55
+ var _ = class {
56
+ constructor(e) {
57
+ this.overlay = null, this.iframe = null, this.spinner = null, this.handleMessage = null, this.handleEscapeKey = null, this.closable = !0, this.iframeLoaded = !1, this.pendingPaymentData = null, this.lastPaymentData = null, this.loadTimer = null, this.unavailableBox = null, this.pendingPrecheck = null, this.config = e, this.walletOrigin = new URL(e.walletUrl).origin, this.createIframe();
58
+ }
59
+ createIframe() {
60
+ let n = document.createElement("div");
61
+ n.className = "pybara-checkout-overlay", n.style.cssText = `
62
+ position: fixed;
63
+ top: 0;
64
+ left: 0;
65
+ right: 0;
66
+ bottom: 0;
67
+ background: ${t.BACKGROUND};
68
+ z-index: ${t.Z_INDEX};
69
+ display: none;
70
+ align-items: center;
71
+ justify-content: center;
72
+ overscroll-behavior: none;
73
+ user-select: none;
74
+ `;
75
+ let r = document.createElement("iframe");
76
+ r.src = `${this.config.walletUrl}/pay?mode=embedded`, r.title = "Pybara Wallet", r.style.cssText = "\n width: 100%;\n max-width: 500px;\n height: 0;\n max-height: 90vh;\n border: none;\n border-radius: 20px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);\n overscroll-behavior: none;\n ";
77
+ let i = document.createElement("div");
78
+ i.setAttribute("aria-hidden", "true"), i.style.cssText = "\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n ", i.innerHTML = "\n <svg viewBox=\"0 0 50 50\" width=\"50\" height=\"50\">\n <circle cx=\"25\" cy=\"25\" r=\"20\" fill=\"none\" stroke=\"white\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-dasharray=\"80\" stroke-dashoffset=\"20\"/>\n </svg>\n ", i.querySelector("svg")?.animate([{ transform: "rotate(0deg)" }, { transform: "rotate(360deg)" }], {
79
+ duration: 1e3,
80
+ iterations: Infinity
81
+ }), r.addEventListener("load", () => this.onIframeLoad(), { once: !0 }), this.handleMessage = (t) => {
82
+ if (t.origin === this.walletOrigin && t.source === r.contentWindow && g(t.data)) switch (t.data.type) {
83
+ case "pybara_embedded_result":
84
+ this.config.onSuccess?.({
85
+ blockIndex: t.data.blockIndex,
86
+ reference: t.data.reference,
87
+ payerPrincipal: t.data.payerPrincipal,
88
+ token: t.data.token
89
+ });
90
+ break;
91
+ case "pybara_embedded_error":
92
+ this.close(), this.config.onError?.(new h(m(t.data.code), t.data.message));
93
+ break;
94
+ case "pybara_embedded_closed":
95
+ this.close(), this.config.onClose?.();
96
+ break;
97
+ case "pybara_embedded_resize":
98
+ this.clearLoadTimer(), this.unavailableBox &&= (this.unavailableBox.remove(), null), r.style.height !== `${t.data.height}px` && (r.style.height = `${t.data.height}px`), this.spinner && (this.spinner.remove(), this.spinner = null, f() || (r.animate([{
99
+ transform: "translateY(20px)",
100
+ opacity: 0
101
+ }, {
102
+ transform: "none",
103
+ opacity: 1
104
+ }], {
105
+ duration: e.PANEL_OPEN_MS,
106
+ easing: "ease"
107
+ }), r.offsetHeight, r.style.transition = `height ${e.RESIZE_MS}ms ${e.RESIZE_EASING}`));
108
+ break;
109
+ case "pybara_embedded_closable":
110
+ this.closable = t.data.closable;
111
+ break;
112
+ case "pybara_embedded_availability": {
113
+ let { type: e, v: n, ...r } = t.data;
114
+ r.status !== "available" && r.detail && console.warn(r.detail), this.config.onAvailability?.(r);
115
+ break;
116
+ }
117
+ }
118
+ }, window.addEventListener("message", this.handleMessage), this.handleEscapeKey = (e) => {
119
+ e.key === "Escape" && this.closable && (this.unavailableBox ? this.closeUnavailable() : (this.close(), this.config.onClose?.()));
120
+ }, document.addEventListener("keydown", this.handleEscapeKey), n.appendChild(i), n.appendChild(r), document.body.appendChild(n), this.overlay = n, this.iframe = r, this.spinner = i;
121
+ }
122
+ onIframeLoad() {
123
+ this.iframeLoaded = !0, this.pendingPrecheck &&= (this.sendPrecheck(this.pendingPrecheck), null), this.pendingPaymentData &&= (this.sendInitMessage(this.pendingPaymentData), null);
124
+ }
125
+ clearLoadTimer() {
126
+ this.loadTimer !== null && (clearTimeout(this.loadTimer), this.loadTimer = null);
127
+ }
128
+ startLoadTimer() {
129
+ this.clearLoadTimer(), this.spinner && (this.loadTimer = setTimeout(() => {
130
+ this.loadTimer = null, this.renderUnavailable();
131
+ }, n));
132
+ }
133
+ renderUnavailable() {
134
+ if (!this.overlay || this.unavailableBox) return;
135
+ this.spinner && (this.spinner.style.display = "none");
136
+ let e = document.createElement("div");
137
+ e.setAttribute("role", "alertdialog"), e.setAttribute("aria-label", "Pybara checkout unavailable"), e.style.cssText = "\n position: absolute;\n background: #fff;\n border-radius: 12px;\n color: #444;\n padding: 1.75rem 2rem;\n line-height: 1.45;\n max-width: 340px;\n text-align: center;\n font-family: system-ui, sans-serif;\n ";
138
+ let t = document.createElement("p");
139
+ t.style.cssText = "margin: 0 0 1.25rem;", t.textContent = "The checkout couldn't load. Check your connection and try again.";
140
+ let n = "font: inherit; padding: 0.55rem 1.2rem; border-radius: 8px; cursor: pointer; margin: 0 0.3rem;", r = document.createElement("button");
141
+ r.type = "button", r.textContent = "Try again", r.style.cssText = `${n} background: #111827; color: #fff; border: 1px solid #111827;`, r.addEventListener("click", () => this.retryLoad());
142
+ let i = document.createElement("button");
143
+ i.type = "button", i.textContent = "Close", i.style.cssText = `${n} background: #fff; color: #111827; border: 1px solid #d1d5db;`, i.addEventListener("click", () => this.closeUnavailable()), e.append(t, r, i), this.overlay.appendChild(e), this.unavailableBox = e, r.focus();
144
+ }
145
+ retryLoad() {
146
+ let e = this.iframe;
147
+ e && (this.unavailableBox?.remove(), this.unavailableBox = null, this.spinner && (this.spinner.style.display = "flex"), this.iframeLoaded = !1, this.pendingPaymentData = this.lastPaymentData, e.addEventListener("load", () => this.onIframeLoad(), { once: !0 }), e.src = `${this.config.walletUrl}/pay?mode=embedded`, this.startLoadTimer());
148
+ }
149
+ closeUnavailable() {
150
+ this.close(), this.config.onError?.(new h("FRAME_UNAVAILABLE", `The Pybara checkout (${this.walletOrigin}/pay) did not load within ${n / 1e3} seconds.`));
151
+ }
152
+ precheck(e) {
153
+ this.iframeLoaded ? this.sendPrecheck(e) : this.pendingPrecheck = e;
154
+ }
155
+ sendPrecheck(e) {
156
+ this.iframe?.contentWindow?.postMessage({
157
+ type: "pybara_embedded_precheck",
158
+ v: 1,
159
+ context: this.config.context,
160
+ ...e
161
+ }, this.walletOrigin);
162
+ }
163
+ sendInitMessage(e) {
164
+ let t = {
165
+ type: "pybara_embedded_init",
166
+ beneficiary: e.modalData.beneficiary,
167
+ salt: e.modalData.salt,
168
+ reference: e.modalData.reference,
169
+ context: this.config.context,
170
+ ...e.recurring ? { recurring: e.recurring } : {},
171
+ checkout: e.checkout,
172
+ ...this.config.thankYouMessage ? { thankYouMessage: this.config.thankYouMessage } : {},
173
+ ...this.config.locale ? { locale: this.config.locale } : {}
174
+ };
175
+ this.iframe?.contentWindow?.postMessage(t, this.walletOrigin);
176
+ }
177
+ open() {
178
+ this.overlay && this.overlay.style.display !== "flex" && (u(), this.overlay.style.display = "flex", f() || this.overlay.animate([{ opacity: 0 }, { opacity: 1 }], {
179
+ duration: e.OVERLAY_FADE_IN_MS,
180
+ easing: "ease"
181
+ }));
182
+ }
183
+ show(e) {
184
+ this.open(), this.lastPaymentData = e, this.startLoadTimer(), this.iframeLoaded ? this.sendInitMessage(e) : this.pendingPaymentData = e;
185
+ }
186
+ renderTerminalState(e) {
187
+ this.close(), u();
188
+ let n = document.createElement("div");
189
+ n.className = "pybara-checkout-overlay", n.style.cssText = `
190
+ position: fixed;
191
+ top: 0;
192
+ left: 0;
193
+ right: 0;
194
+ bottom: 0;
195
+ background: ${t.BACKGROUND};
196
+ z-index: ${t.Z_INDEX};
197
+ display: flex;
198
+ align-items: center;
199
+ justify-content: center;
200
+ user-select: none;
201
+ `;
202
+ let r = document.createElement("div");
203
+ r.style.cssText = "\n background: #fff;\n border-radius: 12px;\n color: #666;\n padding: 2rem;\n line-height: 1.4;\n max-width: 360px;\n text-align: center;\n font-family: system-ui, sans-serif;\n user-select: text;\n ", r.textContent = e, n.appendChild(r), n.addEventListener("click", (e) => {
204
+ e.target === n && (n.remove(), d(), this.config.onClose?.());
205
+ }), document.body.appendChild(n), this.overlay = n;
206
+ }
207
+ close() {
208
+ this.handleMessage &&= (window.removeEventListener("message", this.handleMessage), null), this.handleEscapeKey &&= (document.removeEventListener("keydown", this.handleEscapeKey), null), d();
209
+ let t = this.overlay, n = this.iframe;
210
+ this.overlay = null, this.iframe = null, this.spinner = null, this.iframeLoaded = !1, this.pendingPaymentData = null, this.lastPaymentData = null, this.pendingPrecheck = null, this.closable = !0, this.clearLoadTimer(), this.unavailableBox = null, t && (t.style.display === "none" || f() ? t.remove() : (t.style.pointerEvents = "none", n?.animate([{
211
+ transform: "scale(1)",
212
+ opacity: 1
213
+ }, {
214
+ transform: "scale(0.95)",
215
+ opacity: 0
216
+ }], {
217
+ duration: e.PANEL_CLOSE_MS,
218
+ easing: "ease-out",
219
+ fill: "forwards"
220
+ }), t.animate([{ opacity: 1 }, { opacity: 0 }], {
221
+ duration: e.OVERLAY_FADE_OUT_MS,
222
+ delay: e.OVERLAY_FADE_OUT_DELAY_MS,
223
+ easing: "ease-out",
224
+ fill: "forwards"
225
+ }).finished.then(() => t.remove(), () => t.remove())));
226
+ }
227
+ };
228
+ //#endregion
229
+ export { h as n, _ as t };