@pybara/pybara-js 0.8.0 → 0.9.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.
package/README.md CHANGED
@@ -13,7 +13,7 @@ npm install @pybara/pybara-js
13
13
  No bundler? The IIFE build exposes `window.Pybara` — the same calls as the module:
14
14
 
15
15
  ```html
16
- <script src="https://cdn.jsdelivr.net/npm/@pybara/pybara-js@0.7/dist/pybara-js.iife.js"></script>
16
+ <script src="https://cdn.jsdelivr.net/npm/@pybara/pybara-js@0.9/dist/pybara-js.iife.js"></script>
17
17
  <script>
18
18
  const pybara = Pybara.checkout({ siteUrl, siteName, recipientPrincipal, currency: 'EUR' });
19
19
  pybara.buttons({ createPayment: () => ({ amount: '25' }) }).render('#pybara-button');
@@ -22,7 +22,7 @@ No bundler? The IIFE build exposes `window.Pybara` — the same calls as the mod
22
22
 
23
23
  ## Add Pybara next to PayPal
24
24
 
25
- A page with PayPal Buttons gets a Pybara button beside them in a few lines. Pass the PayPal button's `style` as it is (`color`, `shape`, `height`) and the two match:
25
+ A page with PayPal Buttons gets a Pybara button beside them in a few lines. Pass the PayPal button's `style` as it is (`color`, `shape`, `height`, `borderRadius`) and the two match:
26
26
 
27
27
  ```html
28
28
  <div id="paypal-button-container"></div>
@@ -138,12 +138,12 @@ await pybara.open({ amount: '25', frequency: 'monthly', durationMonths: 12 });
138
138
  | Field | Type | Description |
139
139
  |---|---|---|
140
140
  | `createPayment()` | `function` | **Required.** Called on the click: the payment from the form, as `open()` takes it (`amount`, `currency`, `frequency`, donor fields), without callbacks. May return a promise |
141
- | `style` | `{ color, shape, height }` | `color` `'brand'` \| `'black'` \| `'white'` (PayPal's names; its `'gold'`, `'blue'`, `'silver'` read as `'brand'`), `shape` `'pill'` \| `'rect'` \| `'sharp'`, `height` 25–55 px (default 45). Passed to the button as given |
141
+ | `style` | `{ color, shape, height, borderRadius }` | `color` `'brand'` \| `'black'` \| `'white'` (PayPal's names; its `'gold'`, `'blue'`, `'silver'` read as `'brand'`), `shape` `'pill'` \| `'rect'` \| `'sharp'`, `height` 25–55 px (default 45), `borderRadius` in px, overriding `shape` as PayPal's does. Passed to the button as given |
142
142
  | `hideWhenUnavailable` | `boolean` | Collapse the button instead of leaving its slot empty when Pybara is unavailable |
143
143
  | `onStateChange(availability)` | `function` | The checkout's availability answer, once per answer — see [Availability](#availability) |
144
144
  | `onSuccess(result)` `onError(err)` `onClose()` | `function` | As `open()`'s |
145
145
 
146
- `render(el)` takes an element or a selector, draws the button at the element's full width, and may be called again for another button; `destroy()` removes them all. Several `buttons()` calls share the one checkout.
146
+ `render(el)` takes an element or a selector, draws the button at the element's full width, and may be called again for another button; `destroy()` removes them all. Several `buttons()` calls share the one checkout. From the click until the checkout closes, the button shows "Processing…" in the checkout's `locale`, and takes no second click.
147
147
 
148
148
  ### Availability
149
149
 
@@ -185,11 +185,11 @@ If pybara.io can't be reached, the checkout doesn't spin forever: after 15 secon
185
185
 
186
186
  Today `checkout()` runs the **donation** flow (the `siteUrl` resolves a registered recipient; the frame collects donor details, optional anonymity, tax-receipt flag). Merchant payments ride the same surface when they land — the site's registry record decides the flow, the API doesn't change.
187
187
 
188
- If you want the whole donation *form* — presets, amount selector, frequency picker, styled button — that's [`@pybara/donate-widget`](https://github.com/pybara/pybara-widget), a product built on the same machinery.
188
+ If you want the whole donation *form* — presets, amount selector, frequency picker, styled button — that's [`@pybara/donate-widget`](https://docs.pybara.com/donate-widget/overview/), a product built on the same machinery.
189
189
 
190
190
  ## Internal entry points
191
191
 
192
- `@pybara/pybara-js/modal` and `@pybara/pybara-js/admin` are Pybara's own machinery for its plugins: not part of the public API, with no compatibility promise between versions. Integrate with `Pybara.checkout()`.
192
+ `@pybara/pybara-js/modal`, `@pybara/pybara-js/button` and `@pybara/pybara-js/admin` are Pybara's own machinery for its plugins: not part of the public API, with no compatibility promise between versions. Integrate with `Pybara.checkout()`.
193
193
 
194
194
  ## Links
195
195
 
@@ -159,7 +159,8 @@
159
159
  "properties": {
160
160
  "color": { "type": "string", "description": "'brand' | 'black' | 'white' (PayPal's names; its 'gold', 'blue', 'silver' read as 'brand'). Default 'brand'." },
161
161
  "shape": { "type": "string", "description": "'pill' | 'rect' | 'sharp'. Default 'pill'." },
162
- "height": { "type": "number", "minimum": 25, "maximum": 55, "description": "CSS pixels, PayPal's range. Default 45." }
162
+ "height": { "type": "number", "minimum": 25, "maximum": 55, "description": "CSS pixels, PayPal's range. Default 45." },
163
+ "borderRadius": { "type": "number", "minimum": 0, "description": "CSS pixels, overriding shape's corners, as PayPal's style.borderRadius. Above half the height it draws a pill." }
163
164
  }
164
165
  },
165
166
  "hideWhenUnavailable": { "type": "boolean", "description": "Collapse the button to no height when Pybara is unavailable here; by default its slot stays, empty." },
@@ -0,0 +1,39 @@
1
+ import { Availability } from '../modal/modal';
2
+ import { ButtonsOptions, ButtonStyle, PaymentParams, PybaraButtons } from '../types';
3
+ /** What renderButton() needs: where the button is served, how it looks, the availability answers, and what its click does. */
4
+ export interface RenderButtonOptions {
5
+ /** The wallet the button and its checkout are served from (pybara.io, or staging). */
6
+ walletUrl: string;
7
+ style?: ButtonStyle;
8
+ hideWhenUnavailable?: boolean;
9
+ /** The page's language (BCP 47, e.g. 'fr' or 'fr_FR'), for "Processing…"; English when the wallet doesn't have it. */
10
+ locale?: string;
11
+ /** Subscribes to every availability answer, first with the latest one if there is one; returns the unsubscribe. */
12
+ subscribeAvailability: (listener: (availability: Availability) => void) => () => void;
13
+ /** The payer's click: open the checkout. The button shows "Processing…" until idle() is called, or until this throws or rejects, so handle errors inside it. */
14
+ onClick: () => void | Promise<void>;
15
+ /** Each availability answer, and `unavailable` when the button doesn't load in time. */
16
+ onStateChange?: (availability: Availability) => void;
17
+ }
18
+ /** What renderButton() returns. */
19
+ export interface RenderedButton {
20
+ /** The checkout the click opened has closed or failed: the button shows its mark again and takes clicks. */
21
+ idle(): void;
22
+ /** Remove the button, and stop listening for it. */
23
+ destroy(): void;
24
+ }
25
+ /** What buttons() needs from its checkout: the frame's origin, the page's language, open(), and the availability answers. */
26
+ export interface ButtonsHost {
27
+ walletUrl: string;
28
+ locale?: string;
29
+ /** Resolves true when the checkout is up, false when it opened nothing that will close (a terminal message instead, or one already open). */
30
+ open(payment: PaymentParams): Promise<boolean>;
31
+ subscribeAvailability(listener: (availability: Availability) => void): () => void;
32
+ }
33
+ /**
34
+ * Draw one served Pybara button in the element (or the first element matching the selector), at the style's height and the element's full width.
35
+ * For callers that drive their own checkout, such as the plugins with their CheckoutModal; a page with Pybara.checkout() uses checkout.buttons().
36
+ */
37
+ export declare function renderButton(container: string | HTMLElement, options: RenderButtonOptions): RenderedButton;
38
+ export declare function createButtons(host: ButtonsHost, options: ButtonsOptions): PybaraButtons;
39
+ //# sourceMappingURL=button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/button/button.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAe,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAEtH,8HAA8H;AAC9H,MAAM,WAAW,mBAAmB;IAClC,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,sHAAsH;IACtH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mHAAmH;IACnH,qBAAqB,EAAE,CAAC,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IACtF,gKAAgK;IAChK,OAAO,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,wFAAwF;IACxF,aAAa,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,IAAI,CAAC;CACtD;AAED,mCAAmC;AACnC,MAAM,WAAW,cAAc;IAC7B,4GAA4G;IAC5G,IAAI,IAAI,IAAI,CAAC;IACb,oDAAoD;IACpD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,6HAA6H;AAC7H,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6IAA6I;IAC7I,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,qBAAqB,CAAC,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACnF;AAqBD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,EAAE,OAAO,EAAE,mBAAmB,GAAG,cAAc,CAgF1G;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,GAAG,aAAa,CAoDvF"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @pybara/pybara-js/button
3
+ *
4
+ * The served Pybara button on its own, for a first-party consumer that drives its own checkout (pybara-for-woocommerce's express checkout, with its CheckoutModal): renderButton() draws it and hands its click to the caller.
5
+ * Its own subpath, so a bundle that only draws the button doesn't take the modal with it.
6
+ * Pages use checkout.buttons() on the package root, built on the same renderButton().
7
+ *
8
+ * @internal Not part of the public API: no compatibility promise between versions, even minor ones.
9
+ */
10
+ export { renderButton, type RenderButtonOptions, type RenderedButton } from './button.js';
11
+ export { type ButtonStyle } from '../types.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/button/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1 @@
1
+ export { n as renderButton } from "../button-BEOTKYpw.js";
@@ -0,0 +1,127 @@
1
+ /* Pybara.js - pybara.com */
2
+ import { t as e } from "./config-9RX2E1N4.js";
3
+ //#region src/types.ts
4
+ var t = class extends Error {
5
+ constructor(e, t) {
6
+ super(t), this.name = "PybaraError", this.code = e;
7
+ }
8
+ };
9
+ //#endregion
10
+ //#region src/button/button.ts
11
+ function n(e) {
12
+ let t = typeof e?.height == "number" && Number.isFinite(e.height) ? Math.round(e.height) : 45;
13
+ return Math.min(55, Math.max(25, t));
14
+ }
15
+ function r(e, t) {
16
+ return typeof e?.borderRadius == "number" && Number.isFinite(e.borderRadius) && e.borderRadius >= 0 ? `${e.borderRadius}px` : e?.shape === "sharp" ? "0" : e?.shape === "rect" ? "4px" : `${t / 2}px`;
17
+ }
18
+ function i(e) {
19
+ let n = typeof e == "string" ? document.querySelector(e) : e;
20
+ if (!n) throw new t("INVALID_CONFIG", `render(): no element matches ${JSON.stringify(e)}`);
21
+ return n;
22
+ }
23
+ function a(t, a) {
24
+ let o = i(t), s = new URL(a.walletUrl).origin, c = n(a.style), l = document.createElement("div");
25
+ l.style.cssText = `position:relative;width:100%;height:${c}px;`;
26
+ let u = document.createElement("div");
27
+ u.setAttribute("aria-hidden", "true"), u.style.cssText = `position:absolute;inset:0;border-radius:${r(a.style, c)};background:rgba(128,128,128,0.16);`;
28
+ let d = document.createElement("iframe");
29
+ d.src = `${s}/button`, d.title = "Pybara", d.style.cssText = "position:absolute;inset:0;width:100%;height:100%;border:0;opacity:0;color-scheme:normal;background:transparent;", l.append(u, d), o.appendChild(l);
30
+ let f = !1, p = null, m = (e) => {
31
+ d.contentWindow?.postMessage(e, s);
32
+ }, h = () => m({
33
+ type: "pybara_button_idle",
34
+ v: 1
35
+ }), g = (e) => {
36
+ p = e, f && m({
37
+ type: "pybara_button_availability",
38
+ v: 1,
39
+ status: e.status
40
+ }), a.onStateChange?.(e);
41
+ }, _ = setTimeout(() => {
42
+ if (f) return;
43
+ u.remove(), a.hideWhenUnavailable === !0 && (l.style.height = "0px");
44
+ let t = `Pybara: the button (${s}/button) did not load within ${e / 1e3} seconds; pybara.io may be unreachable from this browser.`;
45
+ console.warn(t), a.onStateChange?.({
46
+ status: "unavailable",
47
+ reason: "BUTTON_UNAVAILABLE",
48
+ detail: t
49
+ });
50
+ }, e);
51
+ d.addEventListener("load", () => {
52
+ m({
53
+ type: "pybara_button_init",
54
+ v: 1,
55
+ style: a.style ?? {},
56
+ hideWhenUnavailable: a.hideWhenUnavailable === !0,
57
+ locale: a.locale,
58
+ busy: !0
59
+ });
60
+ }, { once: !0 });
61
+ let v = (e) => {
62
+ if (e.origin !== s || e.source !== d.contentWindow) return;
63
+ let t = e.data;
64
+ t?.type === "pybara_button_ready" || t?.type === "pybara_button_resize" ? (typeof t.height == "number" && (l.style.height = `${t.height}px`), f || (f = !0, clearTimeout(_), d.style.opacity = "1", u.remove(), p && m({
65
+ type: "pybara_button_availability",
66
+ v: 1,
67
+ status: p.status
68
+ }))) : t?.type === "pybara_button_click" && (async () => {
69
+ try {
70
+ await a.onClick();
71
+ } catch {
72
+ h();
73
+ }
74
+ })();
75
+ };
76
+ window.addEventListener("message", v);
77
+ let y = a.subscribeAvailability(g);
78
+ return {
79
+ idle: h,
80
+ destroy() {
81
+ clearTimeout(_), window.removeEventListener("message", v), y(), l.remove();
82
+ }
83
+ };
84
+ }
85
+ function o(e, n) {
86
+ if (typeof n?.createPayment != "function") throw new t("INVALID_CONFIG", "buttons(): \"createPayment\" is required, a function returning the payment from the form, e.g. () => ({ amount: form.amount.value, currency: \"EUR\" })");
87
+ let r = [], i = () => {
88
+ for (let e of r) e.idle();
89
+ };
90
+ async function o() {
91
+ try {
92
+ let t = await n.createPayment();
93
+ await e.open({
94
+ ...t,
95
+ onSuccess: n.onSuccess,
96
+ onError: (e) => {
97
+ i(), n.onError?.(e);
98
+ },
99
+ onClose: () => {
100
+ i(), n.onClose?.();
101
+ }
102
+ }) || i();
103
+ } catch (e) {
104
+ i(), n.onError?.(e instanceof Error ? e : Error(String(e)));
105
+ }
106
+ }
107
+ function s(t) {
108
+ let i = r.length === 0;
109
+ r.push(a(t, {
110
+ walletUrl: e.walletUrl,
111
+ style: n.style,
112
+ hideWhenUnavailable: n.hideWhenUnavailable,
113
+ locale: e.locale,
114
+ subscribeAvailability: e.subscribeAvailability,
115
+ onClick: o,
116
+ onStateChange: i ? n.onStateChange : void 0
117
+ }));
118
+ }
119
+ return {
120
+ render: s,
121
+ destroy() {
122
+ for (let e of r.splice(0)) e.destroy();
123
+ }
124
+ };
125
+ }
126
+ //#endregion
127
+ export { a as n, t as r, o as t };
@@ -1 +1 @@
1
- {"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../src/checkout.ts"],"names":[],"mappings":"AAMA,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE1D,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,cAAc,EAEnB,KAAK,aAAa,EAElB,KAAK,aAAa,EACnB,MAAM,SAAS,CAAC;AAcjB;;;;;;GAMG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,MAAM,CAAS;IACvB,gIAAgI;IAChI,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,aAAa,CAA8B;IACnD,uGAAuG;IACvG,SAAgB,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,8FAA8F;IAC9F,OAAO,CAAC,YAAY,CAA8C;IAClE,sGAAsG;IACtG,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAmD;IACzF,gEAAgE;IAChE,OAAO,CAAC,kBAAkB,CAA6B;gBAE3C,UAAU,EAAE,cAAc;IAQtC;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa;IAgB/C,OAAO,CAAC,gBAAgB;IAKxB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,IAAI;YAM9D,YAAY;IAkB1B,2IAA2I;IAC3I,IAAI,IAAI,IAAI,UAAU,GAAG,IAAI,CAE5B;IAED;;;;;OAKG;IACG,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA8EjD,4EAA4E;IAC5E,KAAK,IAAI,IAAI;YAIC,IAAI;IA8ClB,OAAO,CAAC,iBAAiB;IAyDzB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAmCnB,6FAA6F;IAC7F,OAAO,CAAC,gBAAgB;CAOzB"}
1
+ {"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../src/checkout.ts"],"names":[],"mappings":"AAMA,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE1D,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,cAAc,EAEnB,KAAK,aAAa,EAElB,KAAK,aAAa,EACnB,MAAM,SAAS,CAAC;AAcjB;;;;;;GAMG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,MAAM,CAAS;IACvB,gIAAgI;IAChI,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,aAAa,CAA8B;IACnD,uGAAuG;IACvG,SAAgB,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,8FAA8F;IAC9F,OAAO,CAAC,YAAY,CAA8C;IAClE,sGAAsG;IACtG,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAmD;IACzF,gEAAgE;IAChE,OAAO,CAAC,kBAAkB,CAA6B;gBAE3C,UAAU,EAAE,cAAc;IAQtC;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa;IAqB/C,OAAO,CAAC,gBAAgB;IAKxB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,IAAI;YAM9D,YAAY;IAkB1B,2IAA2I;IAC3I,IAAI,IAAI,IAAI,UAAU,GAAG,IAAI,CAE5B;IAED;;;;;OAKG;IACG,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA8EjD,4EAA4E;IAC5E,KAAK,IAAI,IAAI;YAIC,IAAI;IA8ClB,OAAO,CAAC,iBAAiB;IAyDzB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAmCnB,6FAA6F;IAC7F,OAAO,CAAC,gBAAgB;CAOzB"}
@@ -0,0 +1,16 @@
1
+ /* Pybara.js - pybara.com */
2
+ //#region src/modal/config.ts
3
+ var e = {
4
+ Z_INDEX: 999999,
5
+ BACKGROUND: "rgba(0, 0, 0, 0.7)"
6
+ }, t = {
7
+ OVERLAY_FADE_IN_MS: 200,
8
+ PANEL_OPEN_MS: 300,
9
+ PANEL_CLOSE_MS: 200,
10
+ OVERLAY_FADE_OUT_DELAY_MS: 50,
11
+ OVERLAY_FADE_OUT_MS: 150,
12
+ RESIZE_MS: 600,
13
+ RESIZE_EASING: ""
14
+ }, n = 15e3;
15
+ //#endregion
16
+ export { t as n, e as r, n as t };
package/dist/index.d.ts CHANGED
@@ -11,5 +11,5 @@ export declare const Pybara: {
11
11
  export { PybaraCheckout } from './checkout';
12
12
  export { type Availability } from './modal/modal';
13
13
  export { type WidgetGate } from './gate';
14
- export { type ButtonPayment, type ButtonsOptions, type CheckoutConfig, type CheckoutResult, type Frequency, type PaymentParams, PybaraError, type PybaraButtons, type PybaraErrorCode, } from './types';
14
+ export { type ButtonPayment, type ButtonsOptions, type ButtonStyle, type CheckoutConfig, type CheckoutResult, type Frequency, type PaymentParams, PybaraError, type PybaraButtons, type PybaraErrorCode, } from './types';
15
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAE/D;AAID,eAAO,MAAM,MAAM;;CAAe,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAE/D;AAID,eAAO,MAAM,MAAM;;CAAe,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,SAAS,CAAC"}
@@ -1 +1 @@
1
- export { t as CheckoutModal, n as EmbeddedError } from "../modal-BiPk8xwF.js";
1
+ export { t as CheckoutModal, n as EmbeddedError } from "../modal-CXTyI_BA.js";
@@ -1,17 +1,7 @@
1
1
  /* Pybara.js - pybara.com */
2
- //#region src/modal/config.ts
3
- var e = {
4
- Z_INDEX: 999999,
5
- BACKGROUND: "rgba(0, 0, 0, 0.7)"
6
- }, t = {
7
- OVERLAY_FADE_IN_MS: 200,
8
- PANEL_OPEN_MS: 300,
9
- PANEL_CLOSE_MS: 200,
10
- OVERLAY_FADE_OUT_DELAY_MS: 50,
11
- OVERLAY_FADE_OUT_MS: 150,
12
- RESIZE_MS: 600,
13
- RESIZE_EASING: ""
14
- }, n = 15e3, r = 0, i = 0, a = 0;
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;
15
5
  function o(e) {
16
6
  e.preventDefault();
17
7
  }
@@ -74,8 +64,8 @@ var _ = class {
74
64
  left: 0;
75
65
  right: 0;
76
66
  bottom: 0;
77
- background: ${e.BACKGROUND};
78
- z-index: ${e.Z_INDEX};
67
+ background: ${t.BACKGROUND};
68
+ z-index: ${t.Z_INDEX};
79
69
  display: none;
80
70
  align-items: center;
81
71
  justify-content: center;
@@ -88,39 +78,39 @@ var _ = class {
88
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)" }], {
89
79
  duration: 1e3,
90
80
  iterations: Infinity
91
- }), r.addEventListener("load", () => this.onIframeLoad(), { once: !0 }), this.handleMessage = (e) => {
92
- if (e.origin === this.walletOrigin && e.source === r.contentWindow && g(e.data)) switch (e.data.type) {
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) {
93
83
  case "pybara_embedded_result":
94
84
  this.config.onSuccess?.({
95
- blockIndex: e.data.blockIndex,
96
- reference: e.data.reference,
97
- payerPrincipal: e.data.payerPrincipal,
98
- token: e.data.token
85
+ blockIndex: t.data.blockIndex,
86
+ reference: t.data.reference,
87
+ payerPrincipal: t.data.payerPrincipal,
88
+ token: t.data.token
99
89
  });
100
90
  break;
101
91
  case "pybara_embedded_error":
102
- this.close(), this.config.onError?.(new h(m(e.data.code), e.data.message));
92
+ this.close(), this.config.onError?.(new h(m(t.data.code), t.data.message));
103
93
  break;
104
94
  case "pybara_embedded_closed":
105
95
  this.close(), this.config.onClose?.();
106
96
  break;
107
97
  case "pybara_embedded_resize":
108
- this.clearLoadTimer(), this.unavailableBox &&= (this.unavailableBox.remove(), null), r.style.height !== `${e.data.height}px` && (r.style.height = `${e.data.height}px`), this.spinner && (this.spinner.remove(), this.spinner = null, f() || (r.animate([{
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([{
109
99
  transform: "translateY(20px)",
110
100
  opacity: 0
111
101
  }, {
112
102
  transform: "none",
113
103
  opacity: 1
114
104
  }], {
115
- duration: t.PANEL_OPEN_MS,
105
+ duration: e.PANEL_OPEN_MS,
116
106
  easing: "ease"
117
- }), r.offsetHeight, r.style.transition = `height ${t.RESIZE_MS}ms ${t.RESIZE_EASING}`));
107
+ }), r.offsetHeight, r.style.transition = `height ${e.RESIZE_MS}ms ${e.RESIZE_EASING}`));
118
108
  break;
119
109
  case "pybara_embedded_closable":
120
- this.closable = e.data.closable;
110
+ this.closable = t.data.closable;
121
111
  break;
122
112
  case "pybara_embedded_availability": {
123
- let { type: t, v: n, ...r } = e.data;
113
+ let { type: e, v: n, ...r } = t.data;
124
114
  r.status !== "available" && r.detail && console.warn(r.detail), this.config.onAvailability?.(r);
125
115
  break;
126
116
  }
@@ -186,14 +176,14 @@ var _ = class {
186
176
  }
187
177
  open() {
188
178
  this.overlay && this.overlay.style.display !== "flex" && (u(), this.overlay.style.display = "flex", f() || this.overlay.animate([{ opacity: 0 }, { opacity: 1 }], {
189
- duration: t.OVERLAY_FADE_IN_MS,
179
+ duration: e.OVERLAY_FADE_IN_MS,
190
180
  easing: "ease"
191
181
  }));
192
182
  }
193
183
  show(e) {
194
184
  this.open(), this.lastPaymentData = e, this.startLoadTimer(), this.iframeLoaded ? this.sendInitMessage(e) : this.pendingPaymentData = e;
195
185
  }
196
- renderTerminalState(t) {
186
+ renderTerminalState(e) {
197
187
  this.close(), u();
198
188
  let n = document.createElement("div");
199
189
  n.className = "pybara-checkout-overlay", n.style.cssText = `
@@ -202,38 +192,38 @@ var _ = class {
202
192
  left: 0;
203
193
  right: 0;
204
194
  bottom: 0;
205
- background: ${e.BACKGROUND};
206
- z-index: ${e.Z_INDEX};
195
+ background: ${t.BACKGROUND};
196
+ z-index: ${t.Z_INDEX};
207
197
  display: flex;
208
198
  align-items: center;
209
199
  justify-content: center;
210
200
  user-select: none;
211
201
  `;
212
202
  let r = document.createElement("div");
213
- 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 = t, n.appendChild(r), n.addEventListener("click", (e) => {
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) => {
214
204
  e.target === n && (n.remove(), d(), this.config.onClose?.());
215
205
  }), document.body.appendChild(n), this.overlay = n;
216
206
  }
217
207
  close() {
218
208
  this.handleMessage &&= (window.removeEventListener("message", this.handleMessage), null), this.handleEscapeKey &&= (document.removeEventListener("keydown", this.handleEscapeKey), null), d();
219
- let e = this.overlay, n = this.iframe;
220
- 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, e && (e.style.display === "none" || f() ? e.remove() : (e.style.pointerEvents = "none", n?.animate([{
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([{
221
211
  transform: "scale(1)",
222
212
  opacity: 1
223
213
  }, {
224
214
  transform: "scale(0.95)",
225
215
  opacity: 0
226
216
  }], {
227
- duration: t.PANEL_CLOSE_MS,
217
+ duration: e.PANEL_CLOSE_MS,
228
218
  easing: "ease-out",
229
219
  fill: "forwards"
230
- }), e.animate([{ opacity: 1 }, { opacity: 0 }], {
231
- duration: t.OVERLAY_FADE_OUT_MS,
232
- delay: t.OVERLAY_FADE_OUT_DELAY_MS,
220
+ }), t.animate([{ opacity: 1 }, { opacity: 0 }], {
221
+ duration: e.OVERLAY_FADE_OUT_MS,
222
+ delay: e.OVERLAY_FADE_OUT_DELAY_MS,
233
223
  easing: "ease-out",
234
224
  fill: "forwards"
235
- }).finished.then(() => e.remove(), () => e.remove())));
225
+ }).finished.then(() => t.remove(), () => t.remove())));
236
226
  }
237
227
  };
238
228
  //#endregion
239
- export { h as n, n as r, _ as t };
229
+ export { h as n, _ as t };
@@ -65,4 +65,4 @@ ic-request`);var ei=new TextEncoder().encode(`\vic-response`);new TextEncoder().
65
65
  text-align: center;
66
66
  font-family: system-ui, sans-serif;
67
67
  user-select: text;
68
- `,n.textContent=e,t.appendChild(n),t.addEventListener(`click`,e=>{e.target===t&&(t.remove(),Qu(),this.config.onClose?.())}),document.body.appendChild(t),this.overlay=t}close(){this.handleMessage&&=(window.removeEventListener(`message`,this.handleMessage),null),this.handleEscapeKey&&=(document.removeEventListener(`keydown`,this.handleEscapeKey),null),Qu();let e=this.overlay,t=this.iframe;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,e&&(e.style.display===`none`||$u()?e.remove():(e.style.pointerEvents=`none`,t?.animate([{transform:`scale(1)`,opacity:1},{transform:`scale(0.95)`,opacity:0}],{duration:Hu.PANEL_CLOSE_MS,easing:`ease-out`,fill:`forwards`}),e.animate([{opacity:1},{opacity:0}],{duration:Hu.OVERLAY_FADE_OUT_MS,delay:Hu.OVERLAY_FADE_OUT_DELAY_MS,easing:`ease-out`,fill:`forwards`}).finished.then(()=>e.remove(),()=>e.remove())))}},ad={widget:`donate-widget`,recurring:`donate-widget-recurring`};function od(e,t){let n=e=>{let t=/^(\d+)-(\d+)$/.exec(e);return t?[Number(t[1]),Number(t[2])]:null},r=n(e),i=n(t);return!r||!i?!1:r[0]>i[0]||r[0]===i[0]&&r[1]>=i[1]}async function sd(e){let t=await fetch(e);if(!t.ok)throw Error(`HTTP ${t.status} from ${e}`);return await t.json()}async function cd(e,t,n){let r=i[e],a=`https://${r.admin_core}.raw.icp0.io/widget-config`,o=`https://${r.admin_regs}.raw.icp0.io/widget-terms?site_url=${encodeURIComponent(t)}&principal=${encodeURIComponent(n)}`,s,c;try{[s,c]=await Promise.all([sd(a),sd(o)])}catch(e){return{show:!1,cause:`unreadable`,reason:`could not read the widget's configuration (${e instanceof Error?e.message:String(e)})`}}let l=s.kill_switch?.plugins??{};return l[ad.widget]?.enabled===!0?!c.signed||!c.version?{show:!1,cause:`terms`,reason:`${t} has not accepted the widget's terms in Pybara Wallet (Manage › Sites › Add a site without a plugin)`}:od(c.version,`1-0`)?{show:!0,recurring:l[ad.recurring]?.enabled===!0}:{show:!1,cause:`terms`,reason:`this widget version requires terms 1-0, and ${t} accepted ${c.version}: accept the new terms in Pybara Wallet (Manage › Sites)`}:{show:!1,cause:`switched-off`,reason:`the widget is switched off by Pybara for now`}}var $=class extends Error{constructor(e,t){super(t),this.name=`PybaraError`,this.code=e}};function ld(e){let t=typeof e?.height==`number`&&Number.isFinite(e.height)?Math.round(e.height):45;return Math.min(55,Math.max(25,t))}function ud(e,t){return e?.shape===`sharp`?`0`:e?.shape===`rect`?`4px`:`${t/2}px`}function dd(e){let t=typeof e==`string`?document.querySelector(e):e;if(!t)throw new $(`INVALID_CONFIG`,`buttons().render(): no element matches ${JSON.stringify(e)}`);return t}function fd(e,t){if(typeof t?.createPayment!=`function`)throw new $(`INVALID_CONFIG`,`buttons(): "createPayment" is required, a function returning the payment from the form, e.g. () => ({ amount: form.amount.value, currency: "EUR" })`);let n=new URL(e.walletUrl).origin,r=[],i=null;async function a(){try{let n=await t.createPayment();await e.open({...n,onSuccess:t.onSuccess,onError:t.onError,onClose:t.onClose})}catch(e){t.onError?.(e instanceof Error?e:Error(String(e)))}}function o(o){let s=dd(o),c=ld(t.style),l=document.createElement(`div`);l.style.cssText=`position:relative;width:100%;height:${c}px;`;let u=document.createElement(`div`);u.setAttribute(`aria-hidden`,`true`),u.style.cssText=`position:absolute;inset:0;border-radius:${ud(t.style,c)};background:rgba(128,128,128,0.16);`;let d=document.createElement(`iframe`);d.src=`${n}/button`,d.title=`Pybara`,d.style.cssText=`position:absolute;inset:0;width:100%;height:100%;border:0;opacity:0;color-scheme:normal;background:transparent;`,l.append(u,d),s.appendChild(l);let f=!1,p=null,m={};i??=m;let h=e=>{d.contentWindow?.postMessage(e,n)},g=e=>{p=e,f&&h({type:`pybara_button_availability`,v:1,status:e.status}),i??=m,i===m&&t.onStateChange?.(e)},_=setTimeout(()=>{if(f)return;u.remove(),t.hideWhenUnavailable===!0&&(l.style.height=`0px`);let e=`Pybara: the button (${n}/button) did not load within ${Uu/1e3} seconds; pybara.io may be unreachable from this browser.`;console.warn(e),i??=m,i===m&&t.onStateChange?.({status:`unavailable`,reason:`BUTTON_UNAVAILABLE`,detail:e})},Uu);d.addEventListener(`load`,()=>{h({type:`pybara_button_init`,v:1,style:t.style??{},hideWhenUnavailable:t.hideWhenUnavailable===!0})},{once:!0});let v=e=>{if(e.origin!==n||e.source!==d.contentWindow)return;let t=e.data;t?.type===`pybara_button_ready`||t?.type===`pybara_button_resize`?(typeof t.height==`number`&&(l.style.height=`${t.height}px`),f||(f=!0,clearTimeout(_),d.style.opacity=`1`,u.remove(),p&&h({type:`pybara_button_availability`,v:1,status:p.status}))):t?.type===`pybara_button_click`&&a()};window.addEventListener(`message`,v);let y=e.subscribeAvailability(g);r.push(()=>{clearTimeout(_),window.removeEventListener(`message`,v),y(),i===m&&(i=null),l.remove()})}return{render:o,destroy(){for(let e of r.splice(0))e()}}}var pd=/^(0|[1-9]\d*)(\.\d+)?$/,md=/^[a-z0-9-]{1,64}$/,hd=class{constructor(e){this.adminClient=null,this.modal=null,this.gateOutcome=null,this.isOpen=!1,this.completedPayment=!1,this.activePayment=null,this.lastPrecheck={},this.availabilityListeners=new Set,this.latestAvailability=null,this.config=vd(e),this.config.onAvailability&&this.availabilityListeners.add(this.config.onAvailability),this.ready=this.init(),this.config.onAvailability&&this.precheck()}buttons(e){return fd({walletUrl:r[this.config.staging?`staging`:`prod`],open:e=>this.open(e),subscribeAvailability:e=>(this.availabilityListeners.add(e),this.latestAvailability?e(this.latestAvailability):!this.config.onAvailability&&this.availabilityListeners.size===1&&this.precheck(this.lastPrecheck),()=>{this.availabilityListeners.delete(e)})},e)}emitAvailability(e){this.latestAvailability=e;for(let t of this.availabilityListeners)t(e)}precheck(e={}){let t=typeof e.amount==`number`&&Number.isFinite(e.amount)?String(e.amount):e.amount;this.lastPrecheck={amount:typeof t==`string`?t:void 0,currency:e.currency??this.config.currency},this.sendPrecheck()}async sendPrecheck(){if(this.availabilityListeners.size===0)return;await this.ready;let e=this.gateOutcome;if(e&&!e.show){let t=e.cause===`unreadable`?{status:`retry-later`,reason:`GATE_UNREADABLE`,detail:`Pybara: ${e.reason}; the checkout tries again at the click.`}:e.cause===`switched-off`?{status:`unavailable`,reason:`SWITCHED_OFF`,detail:`Pybara: ${e.reason}.`}:{status:`unavailable`,reason:`SITE_NOT_READY`,detail:`Pybara: ${e.reason}; the site owner does this, not the page. https://docs.pybara.com/pybara-js/setup/`};t.detail&&console.warn(t.detail),this.emitAvailability(t)}else this.modal?.precheck({beneficiary:this.config.recipientPrincipal,siteUrl:this.config.siteUrl,...this.lastPrecheck})}get gate(){return this.gateOutcome}async open(e){if(await this.ready,this.gateOutcome&&!this.gateOutcome.show)throw new $(`GATE_REFUSED`,this.gateOutcome.reason??`This site cannot accept Pybara payments yet.`);let t=gd(e.amount);if(t===null)throw new $(`INVALID_CONFIG`,`open(): "amount" must be a decimal string in the currency's major units, e.g. "12.34", or a positive number — got ${JSON.stringify(e.amount)}`);let n=e.currency??this.config.currency;if(!n)throw new $(`INVALID_CONFIG`,`open(): "currency" is required — pass it to open(), or set it once in Pybara.checkout()`);if(!/^[A-Z]{3}$/.test(n))throw new $(`INVALID_CONFIG`,`open(): "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(n)}`);if(e.durationMonths!=null&&!e.frequency)throw new $(`INVALID_CONFIG`,`open(): "durationMonths" needs a "frequency"`);let r=e.frequency?{frequency:e.frequency,...e.durationMonths==null?{}:{durationMonths:e.durationMonths}}:void 0;if(r&&this.gateOutcome&&this.gateOutcome.show&&!this.gateOutcome.recurring)throw new $(`GATE_REFUSED`,`Recurring payments are temporarily unavailable.`);if(this.isOpen)return;this.isOpen=!0;let i=!1;try{await this.adminClient?.getRecipientDataWithCache(this.config.siteUrl)}catch(e){this.config.debug&&console.warn(`🧩 pybara-js: recipient access validation failed:`,e),i=!0}this.modal||this.initCheckoutModal();let a=this.modal;if(!a)throw this.isOpen=!1,new $(`CHECKOUT_FAILED`,`The checkout modal could not be initialised.`);if(i)this.isOpen=!1,a.renderTerminalState(`This recipient is currently unable to accept donations.`),this.initCheckoutModal();else{this.activePayment=e;try{a.show({modalData:{beneficiary:this.config.recipientPrincipal,salt:yd(),reference:this.config.siteName},recurring:r,checkout:this.checkoutFor(e,t,n)})}catch(e){throw this.isOpen=!1,this.activePayment=null,bd(e)}}}close(){this.modal?.close()}async init(){let e=this.config.staging?`staging`:`prod`,t=this.config.debug;t&&console.log(`🧩 pybara-js: initializing checkout…`),this.preconnectWallet(e),this.initCheckoutModal();let n=new Bu({adminCoreCanisterId:i[e].admin_core,debug:t});this.adminClient=n;let r=(async()=>{try{await n.init(),await n.getPybaraAdminConfig(),t&&console.log(`🧩 pybara-js: admin client ready`),n.getRecipientDataWithCache(this.config.siteUrl).catch(e=>{t&&console.warn(`🧩 pybara-js: recipient prewarm failed:`,e)})}catch(e){t&&console.error(`🧩 pybara-js: admin client init failed:`,e)}})(),a=(async()=>{this.config.pluginVersion||(this.gateOutcome=await cd(e,this.config.siteUrl,this.config.recipientPrincipal),!this.gateOutcome.show&&t&&console.warn(`🧩 pybara-js: gate refused —`,this.gateOutcome.reason))})();await Promise.all([r,a])}initCheckoutModal(){let e=this.config.staging?`staging`:`prod`,t=this.config,n=this;this.modal=new id({walletUrl:r[e],context:`donation`,thankYouMessage:t.thankYouMessage,locale:t.locale,onAvailability:e=>n.emitAvailability(e),onSuccess:e=>{n.completedPayment=!0;let r=n.activePayment,i=r?.frequency!=null,a={blockIndex:e.blockIndex,reference:e.reference,token:e.token,recurring:i,frequency:r?.frequency,durationMonths:i?r?.durationMonths??void 0:void 0,isUnlimited:i&&r?.durationMonths==null,payerPrincipal:e.payerPrincipal,recipientPrincipal:t.recipientPrincipal};r?.onSuccess?.(a)},onError:e=>{n.isOpen=!1;let t=n.activePayment;n.activePayment=null,t?.onError?.(bd(e)),n.modal=null,n.initCheckoutModal()},onClose:()=>{n.isOpen=!1;let e=n.activePayment;n.activePayment=null,e?.onClose?.(),n.completedPayment&&t.thankYouRedirectUrl?window.location.href=t.thankYouRedirectUrl:(n.completedPayment=!1,n.modal=null,n.initCheckoutModal())}}),this.availabilityListeners.size>0&&this.modal&&Object.keys(this.lastPrecheck).length>0&&this.sendPrecheck()}checkoutFor(e,t,n){let r=this.config;return{v:1,amount:t,currency:n,site:{url:r.siteUrl,name:r.siteName,country:r.siteCountry},platform:r.platform??`pybara-js`,pluginVersion:r.pluginVersion,siteTerms:{version:r.recipientTosVersion,acceptedAt:r.recipientTosAcceptedAt},notify:{email:r.notifyEmail,enabled:r.notifyDonations},donation:{donor:{email:e.donorEmail,firstName:e.donorFirstName,lastName:e.donorLastName,company:e.donorCompany,country:e.donorCountry,address:{line1:e.donorAddressLine1,line2:e.donorAddressLine2,city:e.donorAddressCity,state:e.donorAddressState,postalCode:e.donorAddressPostalCode,country:e.donorAddressCountry},tos:{version:e.donorTosVersion,acceptedAt:e.donorTosAcceptedAt}},message:e.donorMessage,isAnonymous:e.donorIsAnonymous,wantsTaxReceipt:e.wantsTaxReceipt}}}preconnectWallet(e){let t=document.createElement(`link`);t.rel=`preconnect`,t.href=new URL(r[e]).origin,t.crossOrigin=`anonymous`,document.head.appendChild(t)}};function gd(e){let t=typeof e==`number`&&Number.isFinite(e)?String(e):e;return typeof t!=`string`||!pd.test(t)||!/[1-9]/.test(t)?null:t}function _d(e){let t=e.trim();if(!t)return null;let n;try{n=new URL(t.includes(`://`)?t:`https://${t}`)}catch{return null}return n.protocol!==`https:`&&n.protocol!==`http:`?null:n.origin+n.pathname.replace(/\/+$/,``)}function vd(e){if(!e.recipientPrincipal)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "recipientPrincipal" is required`);if(!e.siteUrl)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "siteUrl" is required`);let t=_d(e.siteUrl);if(!t)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "siteUrl" is not a valid http(s) URL: ${e.siteUrl}`);if(!e.siteName)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "siteName" is required`);if(e.currency!=null&&!/^[A-Z]{3}$/.test(e.currency))throw new $(`INVALID_CONFIG`,`Pybara.checkout: "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(e.currency)}`);if(e.platform!=null&&!md.test(e.platform))throw new $(`INVALID_CONFIG`,`Pybara.checkout: "platform" must be a lowercase slug (a-z, 0-9, -), at most 64 characters`);return{...e,siteUrl:t,staging:e.staging??!1,debug:e.debug??!1}}function yd(){let e=crypto.getRandomValues(new Uint8Array(16));return btoa(String.fromCharCode(...e))}function bd(e){return e instanceof Error?e:Error(String(e))}function xd(e){return new hd(e)}return e.Pybara={checkout:xd},e.PybaraCheckout=hd,e.PybaraError=$,e.checkout=xd,e})({});
68
+ `,n.textContent=e,t.appendChild(n),t.addEventListener(`click`,e=>{e.target===t&&(t.remove(),Qu(),this.config.onClose?.())}),document.body.appendChild(t),this.overlay=t}close(){this.handleMessage&&=(window.removeEventListener(`message`,this.handleMessage),null),this.handleEscapeKey&&=(document.removeEventListener(`keydown`,this.handleEscapeKey),null),Qu();let e=this.overlay,t=this.iframe;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,e&&(e.style.display===`none`||$u()?e.remove():(e.style.pointerEvents=`none`,t?.animate([{transform:`scale(1)`,opacity:1},{transform:`scale(0.95)`,opacity:0}],{duration:Hu.PANEL_CLOSE_MS,easing:`ease-out`,fill:`forwards`}),e.animate([{opacity:1},{opacity:0}],{duration:Hu.OVERLAY_FADE_OUT_MS,delay:Hu.OVERLAY_FADE_OUT_DELAY_MS,easing:`ease-out`,fill:`forwards`}).finished.then(()=>e.remove(),()=>e.remove())))}},ad={widget:`donate-widget`,recurring:`donate-widget-recurring`};function od(e,t){let n=e=>{let t=/^(\d+)-(\d+)$/.exec(e);return t?[Number(t[1]),Number(t[2])]:null},r=n(e),i=n(t);return!r||!i?!1:r[0]>i[0]||r[0]===i[0]&&r[1]>=i[1]}async function sd(e){let t=await fetch(e);if(!t.ok)throw Error(`HTTP ${t.status} from ${e}`);return await t.json()}async function cd(e,t,n){let r=i[e],a=`https://${r.admin_core}.raw.icp0.io/widget-config`,o=`https://${r.admin_regs}.raw.icp0.io/widget-terms?site_url=${encodeURIComponent(t)}&principal=${encodeURIComponent(n)}`,s,c;try{[s,c]=await Promise.all([sd(a),sd(o)])}catch(e){return{show:!1,cause:`unreadable`,reason:`could not read the widget's configuration (${e instanceof Error?e.message:String(e)})`}}let l=s.kill_switch?.plugins??{};return l[ad.widget]?.enabled===!0?!c.signed||!c.version?{show:!1,cause:`terms`,reason:`${t} has not accepted the widget's terms in Pybara Wallet (Manage › Sites › Add a site without a plugin)`}:od(c.version,`1-0`)?{show:!0,recurring:l[ad.recurring]?.enabled===!0}:{show:!1,cause:`terms`,reason:`this widget version requires terms 1-0, and ${t} accepted ${c.version}: accept the new terms in Pybara Wallet (Manage › Sites)`}:{show:!1,cause:`switched-off`,reason:`the widget is switched off by Pybara for now`}}var $=class extends Error{constructor(e,t){super(t),this.name=`PybaraError`,this.code=e}};function ld(e){let t=typeof e?.height==`number`&&Number.isFinite(e.height)?Math.round(e.height):45;return Math.min(55,Math.max(25,t))}function ud(e,t){return typeof e?.borderRadius==`number`&&Number.isFinite(e.borderRadius)&&e.borderRadius>=0?`${e.borderRadius}px`:e?.shape===`sharp`?`0`:e?.shape===`rect`?`4px`:`${t/2}px`}function dd(e){let t=typeof e==`string`?document.querySelector(e):e;if(!t)throw new $(`INVALID_CONFIG`,`render(): no element matches ${JSON.stringify(e)}`);return t}function fd(e,t){let n=dd(e),r=new URL(t.walletUrl).origin,i=ld(t.style),a=document.createElement(`div`);a.style.cssText=`position:relative;width:100%;height:${i}px;`;let o=document.createElement(`div`);o.setAttribute(`aria-hidden`,`true`),o.style.cssText=`position:absolute;inset:0;border-radius:${ud(t.style,i)};background:rgba(128,128,128,0.16);`;let s=document.createElement(`iframe`);s.src=`${r}/button`,s.title=`Pybara`,s.style.cssText=`position:absolute;inset:0;width:100%;height:100%;border:0;opacity:0;color-scheme:normal;background:transparent;`,a.append(o,s),n.appendChild(a);let c=!1,l=null,u=e=>{s.contentWindow?.postMessage(e,r)},d=()=>u({type:`pybara_button_idle`,v:1}),f=e=>{l=e,c&&u({type:`pybara_button_availability`,v:1,status:e.status}),t.onStateChange?.(e)},p=setTimeout(()=>{if(c)return;o.remove(),t.hideWhenUnavailable===!0&&(a.style.height=`0px`);let e=`Pybara: the button (${r}/button) did not load within ${Uu/1e3} seconds; pybara.io may be unreachable from this browser.`;console.warn(e),t.onStateChange?.({status:`unavailable`,reason:`BUTTON_UNAVAILABLE`,detail:e})},Uu);s.addEventListener(`load`,()=>{u({type:`pybara_button_init`,v:1,style:t.style??{},hideWhenUnavailable:t.hideWhenUnavailable===!0,locale:t.locale,busy:!0})},{once:!0});let m=e=>{if(e.origin!==r||e.source!==s.contentWindow)return;let n=e.data;n?.type===`pybara_button_ready`||n?.type===`pybara_button_resize`?(typeof n.height==`number`&&(a.style.height=`${n.height}px`),c||(c=!0,clearTimeout(p),s.style.opacity=`1`,o.remove(),l&&u({type:`pybara_button_availability`,v:1,status:l.status}))):n?.type===`pybara_button_click`&&(async()=>{try{await t.onClick()}catch{d()}})()};window.addEventListener(`message`,m);let h=t.subscribeAvailability(f);return{idle:d,destroy(){clearTimeout(p),window.removeEventListener(`message`,m),h(),a.remove()}}}function pd(e,t){if(typeof t?.createPayment!=`function`)throw new $(`INVALID_CONFIG`,`buttons(): "createPayment" is required, a function returning the payment from the form, e.g. () => ({ amount: form.amount.value, currency: "EUR" })`);let n=[],r=()=>{for(let e of n)e.idle()};async function i(){try{let n=await t.createPayment();await e.open({...n,onSuccess:t.onSuccess,onError:e=>{r(),t.onError?.(e)},onClose:()=>{r(),t.onClose?.()}})||r()}catch(e){r(),t.onError?.(e instanceof Error?e:Error(String(e)))}}function a(r){let a=n.length===0;n.push(fd(r,{walletUrl:e.walletUrl,style:t.style,hideWhenUnavailable:t.hideWhenUnavailable,locale:e.locale,subscribeAvailability:e.subscribeAvailability,onClick:i,onStateChange:a?t.onStateChange:void 0}))}return{render:a,destroy(){for(let e of n.splice(0))e.destroy()}}}var md=/^(0|[1-9]\d*)(\.\d+)?$/,hd=/^[a-z0-9-]{1,64}$/,gd=class{constructor(e){this.adminClient=null,this.modal=null,this.gateOutcome=null,this.isOpen=!1,this.completedPayment=!1,this.activePayment=null,this.lastPrecheck={},this.availabilityListeners=new Set,this.latestAvailability=null,this.config=yd(e),this.config.onAvailability&&this.availabilityListeners.add(this.config.onAvailability),this.ready=this.init(),this.config.onAvailability&&this.precheck()}buttons(e){return pd({walletUrl:r[this.config.staging?`staging`:`prod`],locale:this.config.locale,open:async e=>(await this.open(e),this.activePayment===e),subscribeAvailability:e=>(this.availabilityListeners.add(e),this.latestAvailability?e(this.latestAvailability):!this.config.onAvailability&&this.availabilityListeners.size===1&&this.precheck(this.lastPrecheck),()=>{this.availabilityListeners.delete(e)})},e)}emitAvailability(e){this.latestAvailability=e;for(let t of this.availabilityListeners)t(e)}precheck(e={}){let t=typeof e.amount==`number`&&Number.isFinite(e.amount)?String(e.amount):e.amount;this.lastPrecheck={amount:typeof t==`string`?t:void 0,currency:e.currency??this.config.currency},this.sendPrecheck()}async sendPrecheck(){if(this.availabilityListeners.size===0)return;await this.ready;let e=this.gateOutcome;if(e&&!e.show){let t=e.cause===`unreadable`?{status:`retry-later`,reason:`GATE_UNREADABLE`,detail:`Pybara: ${e.reason}; the checkout tries again at the click.`}:e.cause===`switched-off`?{status:`unavailable`,reason:`SWITCHED_OFF`,detail:`Pybara: ${e.reason}.`}:{status:`unavailable`,reason:`SITE_NOT_READY`,detail:`Pybara: ${e.reason}; the site owner does this, not the page. https://docs.pybara.com/pybara-js/setup/`};t.detail&&console.warn(t.detail),this.emitAvailability(t)}else this.modal?.precheck({beneficiary:this.config.recipientPrincipal,siteUrl:this.config.siteUrl,...this.lastPrecheck})}get gate(){return this.gateOutcome}async open(e){if(await this.ready,this.gateOutcome&&!this.gateOutcome.show)throw new $(`GATE_REFUSED`,this.gateOutcome.reason??`This site cannot accept Pybara payments yet.`);let t=_d(e.amount);if(t===null)throw new $(`INVALID_CONFIG`,`open(): "amount" must be a decimal string in the currency's major units, e.g. "12.34", or a positive number — got ${JSON.stringify(e.amount)}`);let n=e.currency??this.config.currency;if(!n)throw new $(`INVALID_CONFIG`,`open(): "currency" is required — pass it to open(), or set it once in Pybara.checkout()`);if(!/^[A-Z]{3}$/.test(n))throw new $(`INVALID_CONFIG`,`open(): "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(n)}`);if(e.durationMonths!=null&&!e.frequency)throw new $(`INVALID_CONFIG`,`open(): "durationMonths" needs a "frequency"`);let r=e.frequency?{frequency:e.frequency,...e.durationMonths==null?{}:{durationMonths:e.durationMonths}}:void 0;if(r&&this.gateOutcome&&this.gateOutcome.show&&!this.gateOutcome.recurring)throw new $(`GATE_REFUSED`,`Recurring payments are temporarily unavailable.`);if(this.isOpen)return;this.isOpen=!0;let i=!1;try{await this.adminClient?.getRecipientDataWithCache(this.config.siteUrl)}catch(e){this.config.debug&&console.warn(`🧩 pybara-js: recipient access validation failed:`,e),i=!0}this.modal||this.initCheckoutModal();let a=this.modal;if(!a)throw this.isOpen=!1,new $(`CHECKOUT_FAILED`,`The checkout modal could not be initialised.`);if(i)this.isOpen=!1,a.renderTerminalState(`This recipient is currently unable to accept donations.`),this.initCheckoutModal();else{this.activePayment=e;try{a.show({modalData:{beneficiary:this.config.recipientPrincipal,salt:bd(),reference:this.config.siteName},recurring:r,checkout:this.checkoutFor(e,t,n)})}catch(e){throw this.isOpen=!1,this.activePayment=null,xd(e)}}}close(){this.modal?.close()}async init(){let e=this.config.staging?`staging`:`prod`,t=this.config.debug;t&&console.log(`🧩 pybara-js: initializing checkout…`),this.preconnectWallet(e),this.initCheckoutModal();let n=new Bu({adminCoreCanisterId:i[e].admin_core,debug:t});this.adminClient=n;let r=(async()=>{try{await n.init(),await n.getPybaraAdminConfig(),t&&console.log(`🧩 pybara-js: admin client ready`),n.getRecipientDataWithCache(this.config.siteUrl).catch(e=>{t&&console.warn(`🧩 pybara-js: recipient prewarm failed:`,e)})}catch(e){t&&console.error(`🧩 pybara-js: admin client init failed:`,e)}})(),a=(async()=>{this.config.pluginVersion||(this.gateOutcome=await cd(e,this.config.siteUrl,this.config.recipientPrincipal),!this.gateOutcome.show&&t&&console.warn(`🧩 pybara-js: gate refused —`,this.gateOutcome.reason))})();await Promise.all([r,a])}initCheckoutModal(){let e=this.config.staging?`staging`:`prod`,t=this.config,n=this;this.modal=new id({walletUrl:r[e],context:`donation`,thankYouMessage:t.thankYouMessage,locale:t.locale,onAvailability:e=>n.emitAvailability(e),onSuccess:e=>{n.completedPayment=!0;let r=n.activePayment,i=r?.frequency!=null,a={blockIndex:e.blockIndex,reference:e.reference,token:e.token,recurring:i,frequency:r?.frequency,durationMonths:i?r?.durationMonths??void 0:void 0,isUnlimited:i&&r?.durationMonths==null,payerPrincipal:e.payerPrincipal,recipientPrincipal:t.recipientPrincipal};r?.onSuccess?.(a)},onError:e=>{n.isOpen=!1;let t=n.activePayment;n.activePayment=null,t?.onError?.(xd(e)),n.modal=null,n.initCheckoutModal()},onClose:()=>{n.isOpen=!1;let e=n.activePayment;n.activePayment=null,e?.onClose?.(),n.completedPayment&&t.thankYouRedirectUrl?window.location.href=t.thankYouRedirectUrl:(n.completedPayment=!1,n.modal=null,n.initCheckoutModal())}}),this.availabilityListeners.size>0&&this.modal&&Object.keys(this.lastPrecheck).length>0&&this.sendPrecheck()}checkoutFor(e,t,n){let r=this.config;return{v:1,amount:t,currency:n,site:{url:r.siteUrl,name:r.siteName,country:r.siteCountry},platform:r.platform??`pybara-js`,pluginVersion:r.pluginVersion,siteTerms:{version:r.recipientTosVersion,acceptedAt:r.recipientTosAcceptedAt},notify:{email:r.notifyEmail,enabled:r.notifyDonations},donation:{donor:{email:e.donorEmail,firstName:e.donorFirstName,lastName:e.donorLastName,company:e.donorCompany,country:e.donorCountry,address:{line1:e.donorAddressLine1,line2:e.donorAddressLine2,city:e.donorAddressCity,state:e.donorAddressState,postalCode:e.donorAddressPostalCode,country:e.donorAddressCountry},tos:{version:e.donorTosVersion,acceptedAt:e.donorTosAcceptedAt}},message:e.donorMessage,isAnonymous:e.donorIsAnonymous,wantsTaxReceipt:e.wantsTaxReceipt}}}preconnectWallet(e){let t=document.createElement(`link`);t.rel=`preconnect`,t.href=new URL(r[e]).origin,t.crossOrigin=`anonymous`,document.head.appendChild(t)}};function _d(e){let t=typeof e==`number`&&Number.isFinite(e)?String(e):e;return typeof t!=`string`||!md.test(t)||!/[1-9]/.test(t)?null:t}function vd(e){let t=e.trim();if(!t)return null;let n;try{n=new URL(t.includes(`://`)?t:`https://${t}`)}catch{return null}return n.protocol!==`https:`&&n.protocol!==`http:`?null:n.origin+n.pathname.replace(/\/+$/,``)}function yd(e){if(!e.recipientPrincipal)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "recipientPrincipal" is required`);if(!e.siteUrl)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "siteUrl" is required`);let t=vd(e.siteUrl);if(!t)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "siteUrl" is not a valid http(s) URL: ${e.siteUrl}`);if(!e.siteName)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "siteName" is required`);if(e.currency!=null&&!/^[A-Z]{3}$/.test(e.currency))throw new $(`INVALID_CONFIG`,`Pybara.checkout: "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(e.currency)}`);if(e.platform!=null&&!hd.test(e.platform))throw new $(`INVALID_CONFIG`,`Pybara.checkout: "platform" must be a lowercase slug (a-z, 0-9, -), at most 64 characters`);return{...e,siteUrl:t,staging:e.staging??!1,debug:e.debug??!1}}function bd(){let e=crypto.getRandomValues(new Uint8Array(16));return btoa(String.fromCharCode(...e))}function xd(e){return e instanceof Error?e:Error(String(e))}function Sd(e){return new gd(e)}return e.Pybara={checkout:Sd},e.PybaraCheckout=gd,e.PybaraError=$,e.checkout=Sd,e})({});
package/dist/pybara-js.js CHANGED
@@ -1,26 +1,27 @@
1
1
  /* Pybara.js - pybara.com */
2
2
  import { n as e, r as t, t as n } from "./admin-B1pVP25-.js";
3
- import { r, t as i } from "./modal-BiPk8xwF.js";
4
- var a = {
3
+ import { t as r } from "./modal-CXTyI_BA.js";
4
+ import { r as i, t as a } from "./button-BEOTKYpw.js";
5
+ var o = {
5
6
  widget: "donate-widget",
6
7
  recurring: "donate-widget-recurring"
7
8
  };
8
- function o(e, t) {
9
+ function s(e, t) {
9
10
  let n = (e) => {
10
11
  let t = /^(\d+)-(\d+)$/.exec(e);
11
12
  return t ? [Number(t[1]), Number(t[2])] : null;
12
13
  }, r = n(e), i = n(t);
13
14
  return !r || !i ? !1 : r[0] > i[0] || r[0] === i[0] && r[1] >= i[1];
14
15
  }
15
- async function s(e) {
16
+ async function c(e) {
16
17
  let t = await fetch(e);
17
18
  if (!t.ok) throw Error(`HTTP ${t.status} from ${e}`);
18
19
  return await t.json();
19
20
  }
20
- async function c(t, n, r) {
21
- let i = e[t], c = `https://${i.admin_core}.raw.icp0.io/widget-config`, l = `https://${i.admin_regs}.raw.icp0.io/widget-terms?site_url=${encodeURIComponent(n)}&principal=${encodeURIComponent(r)}`, u, d;
21
+ async function l(t, n, r) {
22
+ let i = e[t], a = `https://${i.admin_core}.raw.icp0.io/widget-config`, l = `https://${i.admin_regs}.raw.icp0.io/widget-terms?site_url=${encodeURIComponent(n)}&principal=${encodeURIComponent(r)}`, u, d;
22
23
  try {
23
- [u, d] = await Promise.all([s(c), s(l)]);
24
+ [u, d] = await Promise.all([c(a), c(l)]);
24
25
  } catch (e) {
25
26
  return {
26
27
  show: !1,
@@ -29,13 +30,13 @@ async function c(t, n, r) {
29
30
  };
30
31
  }
31
32
  let f = u.kill_switch?.plugins ?? {};
32
- return f[a.widget]?.enabled === !0 ? !d.signed || !d.version ? {
33
+ return f[o.widget]?.enabled === !0 ? !d.signed || !d.version ? {
33
34
  show: !1,
34
35
  cause: "terms",
35
36
  reason: `${n} has not accepted the widget's terms in Pybara Wallet (Manage › Sites › Add a site without a plugin)`
36
- } : o(d.version, "1-0") ? {
37
+ } : s(d.version, "1-0") ? {
37
38
  show: !0,
38
- recurring: f[a.recurring]?.enabled === !0
39
+ recurring: f[o.recurring]?.enabled === !0
39
40
  } : {
40
41
  show: !1,
41
42
  cause: "terms",
@@ -47,109 +48,16 @@ async function c(t, n, r) {
47
48
  };
48
49
  }
49
50
  //#endregion
50
- //#region src/types.ts
51
- var l = class extends Error {
52
- constructor(e, t) {
53
- super(t), this.name = "PybaraError", this.code = e;
54
- }
55
- };
56
- //#endregion
57
- //#region src/buttons.ts
58
- function u(e) {
59
- let t = typeof e?.height == "number" && Number.isFinite(e.height) ? Math.round(e.height) : 45;
60
- return Math.min(55, Math.max(25, t));
61
- }
62
- function d(e, t) {
63
- return e?.shape === "sharp" ? "0" : e?.shape === "rect" ? "4px" : `${t / 2}px`;
64
- }
65
- function f(e) {
66
- let t = typeof e == "string" ? document.querySelector(e) : e;
67
- if (!t) throw new l("INVALID_CONFIG", `buttons().render(): no element matches ${JSON.stringify(e)}`);
68
- return t;
69
- }
70
- function p(e, t) {
71
- if (typeof t?.createPayment != "function") throw new l("INVALID_CONFIG", "buttons(): \"createPayment\" is required, a function returning the payment from the form, e.g. () => ({ amount: form.amount.value, currency: \"EUR\" })");
72
- let n = new URL(e.walletUrl).origin, i = [], a = null;
73
- async function o() {
74
- try {
75
- let n = await t.createPayment();
76
- await e.open({
77
- ...n,
78
- onSuccess: t.onSuccess,
79
- onError: t.onError,
80
- onClose: t.onClose
81
- });
82
- } catch (e) {
83
- t.onError?.(e instanceof Error ? e : Error(String(e)));
84
- }
85
- }
86
- function s(s) {
87
- let c = f(s), l = u(t.style), p = document.createElement("div");
88
- p.style.cssText = `position:relative;width:100%;height:${l}px;`;
89
- let m = document.createElement("div");
90
- m.setAttribute("aria-hidden", "true"), m.style.cssText = `position:absolute;inset:0;border-radius:${d(t.style, l)};background:rgba(128,128,128,0.16);`;
91
- let h = document.createElement("iframe");
92
- h.src = `${n}/button`, h.title = "Pybara", h.style.cssText = "position:absolute;inset:0;width:100%;height:100%;border:0;opacity:0;color-scheme:normal;background:transparent;", p.append(m, h), c.appendChild(p);
93
- let g = !1, _ = null, v = {};
94
- a ??= v;
95
- let y = (e) => {
96
- h.contentWindow?.postMessage(e, n);
97
- }, b = (e) => {
98
- _ = e, g && y({
99
- type: "pybara_button_availability",
100
- v: 1,
101
- status: e.status
102
- }), a ??= v, a === v && t.onStateChange?.(e);
103
- }, x = setTimeout(() => {
104
- if (g) return;
105
- m.remove(), t.hideWhenUnavailable === !0 && (p.style.height = "0px");
106
- let e = `Pybara: the button (${n}/button) did not load within ${r / 1e3} seconds; pybara.io may be unreachable from this browser.`;
107
- console.warn(e), a ??= v, a === v && t.onStateChange?.({
108
- status: "unavailable",
109
- reason: "BUTTON_UNAVAILABLE",
110
- detail: e
111
- });
112
- }, r);
113
- h.addEventListener("load", () => {
114
- y({
115
- type: "pybara_button_init",
116
- v: 1,
117
- style: t.style ?? {},
118
- hideWhenUnavailable: t.hideWhenUnavailable === !0
119
- });
120
- }, { once: !0 });
121
- let S = (e) => {
122
- if (e.origin !== n || e.source !== h.contentWindow) return;
123
- let t = e.data;
124
- t?.type === "pybara_button_ready" || t?.type === "pybara_button_resize" ? (typeof t.height == "number" && (p.style.height = `${t.height}px`), g || (g = !0, clearTimeout(x), h.style.opacity = "1", m.remove(), _ && y({
125
- type: "pybara_button_availability",
126
- v: 1,
127
- status: _.status
128
- }))) : t?.type === "pybara_button_click" && o();
129
- };
130
- window.addEventListener("message", S);
131
- let C = e.subscribeAvailability(b);
132
- i.push(() => {
133
- clearTimeout(x), window.removeEventListener("message", S), C(), a === v && (a = null), p.remove();
134
- });
135
- }
136
- return {
137
- render: s,
138
- destroy() {
139
- for (let e of i.splice(0)) e();
140
- }
141
- };
142
- }
143
- //#endregion
144
51
  //#region src/checkout.ts
145
- var m = /^(0|[1-9]\d*)(\.\d+)?$/, h = /^[a-z0-9-]{1,64}$/, g = class {
52
+ var u = /^(0|[1-9]\d*)(\.\d+)?$/, d = /^[a-z0-9-]{1,64}$/, f = class {
146
53
  constructor(e) {
147
- this.adminClient = null, this.modal = null, this.gateOutcome = null, this.isOpen = !1, this.completedPayment = !1, this.activePayment = null, this.lastPrecheck = {}, this.availabilityListeners = /* @__PURE__ */ new Set(), this.latestAvailability = null, this.config = y(e), this.config.onAvailability && this.availabilityListeners.add(this.config.onAvailability), this.ready = this.init(), this.config.onAvailability && this.precheck();
54
+ this.adminClient = null, this.modal = null, this.gateOutcome = null, this.isOpen = !1, this.completedPayment = !1, this.activePayment = null, this.lastPrecheck = {}, this.availabilityListeners = /* @__PURE__ */ new Set(), this.latestAvailability = null, this.config = h(e), this.config.onAvailability && this.availabilityListeners.add(this.config.onAvailability), this.ready = this.init(), this.config.onAvailability && this.precheck();
148
55
  }
149
56
  buttons(e) {
150
- return p({
57
+ return a({
151
58
  walletUrl: t[this.config.staging ? "staging" : "prod"],
152
- open: (e) => this.open(e),
59
+ locale: this.config.locale,
60
+ open: async (e) => (await this.open(e), this.activePayment === e),
153
61
  subscribeAvailability: (e) => (this.availabilityListeners.add(e), this.latestAvailability ? e(this.latestAvailability) : !this.config.onAvailability && this.availabilityListeners.size === 1 && this.precheck(this.lastPrecheck), () => {
154
62
  this.availabilityListeners.delete(e);
155
63
  })
@@ -195,44 +103,44 @@ var m = /^(0|[1-9]\d*)(\.\d+)?$/, h = /^[a-z0-9-]{1,64}$/, g = class {
195
103
  return this.gateOutcome;
196
104
  }
197
105
  async open(e) {
198
- if (await this.ready, this.gateOutcome && !this.gateOutcome.show) throw new l("GATE_REFUSED", this.gateOutcome.reason ?? "This site cannot accept Pybara payments yet.");
199
- let t = _(e.amount);
200
- if (t === null) throw new l("INVALID_CONFIG", `open(): "amount" must be a decimal string in the currency's major units, e.g. "12.34", or a positive number — got ${JSON.stringify(e.amount)}`);
106
+ if (await this.ready, this.gateOutcome && !this.gateOutcome.show) throw new i("GATE_REFUSED", this.gateOutcome.reason ?? "This site cannot accept Pybara payments yet.");
107
+ let t = p(e.amount);
108
+ if (t === null) throw new i("INVALID_CONFIG", `open(): "amount" must be a decimal string in the currency's major units, e.g. "12.34", or a positive number — got ${JSON.stringify(e.amount)}`);
201
109
  let n = e.currency ?? this.config.currency;
202
- if (!n) throw new l("INVALID_CONFIG", "open(): \"currency\" is required — pass it to open(), or set it once in Pybara.checkout()");
203
- if (!/^[A-Z]{3}$/.test(n)) throw new l("INVALID_CONFIG", `open(): "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(n)}`);
204
- if (e.durationMonths != null && !e.frequency) throw new l("INVALID_CONFIG", "open(): \"durationMonths\" needs a \"frequency\"");
110
+ if (!n) throw new i("INVALID_CONFIG", "open(): \"currency\" is required — pass it to open(), or set it once in Pybara.checkout()");
111
+ if (!/^[A-Z]{3}$/.test(n)) throw new i("INVALID_CONFIG", `open(): "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(n)}`);
112
+ if (e.durationMonths != null && !e.frequency) throw new i("INVALID_CONFIG", "open(): \"durationMonths\" needs a \"frequency\"");
205
113
  let r = e.frequency ? {
206
114
  frequency: e.frequency,
207
115
  ...e.durationMonths == null ? {} : { durationMonths: e.durationMonths }
208
116
  } : void 0;
209
- if (r && this.gateOutcome && this.gateOutcome.show && !this.gateOutcome.recurring) throw new l("GATE_REFUSED", "Recurring payments are temporarily unavailable.");
117
+ if (r && this.gateOutcome && this.gateOutcome.show && !this.gateOutcome.recurring) throw new i("GATE_REFUSED", "Recurring payments are temporarily unavailable.");
210
118
  if (this.isOpen) return;
211
119
  this.isOpen = !0;
212
- let i = !1;
120
+ let a = !1;
213
121
  try {
214
122
  await this.adminClient?.getRecipientDataWithCache(this.config.siteUrl);
215
123
  } catch (e) {
216
- this.config.debug && console.warn("🧩 pybara-js: recipient access validation failed:", e), i = !0;
124
+ this.config.debug && console.warn("🧩 pybara-js: recipient access validation failed:", e), a = !0;
217
125
  }
218
126
  this.modal || this.initCheckoutModal();
219
- let a = this.modal;
220
- if (!a) throw this.isOpen = !1, new l("CHECKOUT_FAILED", "The checkout modal could not be initialised.");
221
- if (i) this.isOpen = !1, a.renderTerminalState("This recipient is currently unable to accept donations."), this.initCheckoutModal();
127
+ let o = this.modal;
128
+ if (!o) throw this.isOpen = !1, new i("CHECKOUT_FAILED", "The checkout modal could not be initialised.");
129
+ if (a) this.isOpen = !1, o.renderTerminalState("This recipient is currently unable to accept donations."), this.initCheckoutModal();
222
130
  else {
223
131
  this.activePayment = e;
224
132
  try {
225
- a.show({
133
+ o.show({
226
134
  modalData: {
227
135
  beneficiary: this.config.recipientPrincipal,
228
- salt: b(),
136
+ salt: g(),
229
137
  reference: this.config.siteName
230
138
  },
231
139
  recurring: r,
232
140
  checkout: this.checkoutFor(e, t, n)
233
141
  });
234
142
  } catch (e) {
235
- throw this.isOpen = !1, this.activePayment = null, x(e);
143
+ throw this.isOpen = !1, this.activePayment = null, _(e);
236
144
  }
237
145
  }
238
146
  }
@@ -256,42 +164,42 @@ var m = /^(0|[1-9]\d*)(\.\d+)?$/, h = /^[a-z0-9-]{1,64}$/, g = class {
256
164
  r && console.error("🧩 pybara-js: admin client init failed:", e);
257
165
  }
258
166
  })(), o = (async () => {
259
- this.config.pluginVersion || (this.gateOutcome = await c(t, this.config.siteUrl, this.config.recipientPrincipal), !this.gateOutcome.show && r && console.warn("🧩 pybara-js: gate refused —", this.gateOutcome.reason));
167
+ this.config.pluginVersion || (this.gateOutcome = await l(t, this.config.siteUrl, this.config.recipientPrincipal), !this.gateOutcome.show && r && console.warn("🧩 pybara-js: gate refused —", this.gateOutcome.reason));
260
168
  })();
261
169
  await Promise.all([a, o]);
262
170
  }
263
171
  initCheckoutModal() {
264
- let e = this.config.staging ? "staging" : "prod", n = this.config, r = this;
265
- this.modal = new i({
172
+ let e = this.config.staging ? "staging" : "prod", n = this.config, i = this;
173
+ this.modal = new r({
266
174
  walletUrl: t[e],
267
175
  context: "donation",
268
176
  thankYouMessage: n.thankYouMessage,
269
177
  locale: n.locale,
270
- onAvailability: (e) => r.emitAvailability(e),
178
+ onAvailability: (e) => i.emitAvailability(e),
271
179
  onSuccess: (e) => {
272
- r.completedPayment = !0;
273
- let t = r.activePayment, i = t?.frequency != null, a = {
180
+ i.completedPayment = !0;
181
+ let t = i.activePayment, r = t?.frequency != null, a = {
274
182
  blockIndex: e.blockIndex,
275
183
  reference: e.reference,
276
184
  token: e.token,
277
- recurring: i,
185
+ recurring: r,
278
186
  frequency: t?.frequency,
279
- durationMonths: i ? t?.durationMonths ?? void 0 : void 0,
280
- isUnlimited: i && t?.durationMonths == null,
187
+ durationMonths: r ? t?.durationMonths ?? void 0 : void 0,
188
+ isUnlimited: r && t?.durationMonths == null,
281
189
  payerPrincipal: e.payerPrincipal,
282
190
  recipientPrincipal: n.recipientPrincipal
283
191
  };
284
192
  t?.onSuccess?.(a);
285
193
  },
286
194
  onError: (e) => {
287
- r.isOpen = !1;
288
- let t = r.activePayment;
289
- r.activePayment = null, t?.onError?.(x(e)), r.modal = null, r.initCheckoutModal();
195
+ i.isOpen = !1;
196
+ let t = i.activePayment;
197
+ i.activePayment = null, t?.onError?.(_(e)), i.modal = null, i.initCheckoutModal();
290
198
  },
291
199
  onClose: () => {
292
- r.isOpen = !1;
293
- let e = r.activePayment;
294
- r.activePayment = null, e?.onClose?.(), r.completedPayment && n.thankYouRedirectUrl ? window.location.href = n.thankYouRedirectUrl : (r.completedPayment = !1, r.modal = null, r.initCheckoutModal());
200
+ i.isOpen = !1;
201
+ let e = i.activePayment;
202
+ i.activePayment = null, e?.onClose?.(), i.completedPayment && n.thankYouRedirectUrl ? window.location.href = n.thankYouRedirectUrl : (i.completedPayment = !1, i.modal = null, i.initCheckoutModal());
295
203
  }
296
204
  }), this.availabilityListeners.size > 0 && this.modal && Object.keys(this.lastPrecheck).length > 0 && this.sendPrecheck();
297
205
  }
@@ -347,11 +255,11 @@ var m = /^(0|[1-9]\d*)(\.\d+)?$/, h = /^[a-z0-9-]{1,64}$/, g = class {
347
255
  n.rel = "preconnect", n.href = new URL(t[e]).origin, n.crossOrigin = "anonymous", document.head.appendChild(n);
348
256
  }
349
257
  };
350
- function _(e) {
258
+ function p(e) {
351
259
  let t = typeof e == "number" && Number.isFinite(e) ? String(e) : e;
352
- return typeof t != "string" || !m.test(t) || !/[1-9]/.test(t) ? null : t;
260
+ return typeof t != "string" || !u.test(t) || !/[1-9]/.test(t) ? null : t;
353
261
  }
354
- function v(e) {
262
+ function m(e) {
355
263
  let t = e.trim();
356
264
  if (!t) return null;
357
265
  let n;
@@ -362,14 +270,14 @@ function v(e) {
362
270
  }
363
271
  return n.protocol !== "https:" && n.protocol !== "http:" ? null : n.origin + n.pathname.replace(/\/+$/, "");
364
272
  }
365
- function y(e) {
366
- if (!e.recipientPrincipal) throw new l("INVALID_CONFIG", "Pybara.checkout: \"recipientPrincipal\" is required");
367
- if (!e.siteUrl) throw new l("INVALID_CONFIG", "Pybara.checkout: \"siteUrl\" is required");
368
- let t = v(e.siteUrl);
369
- if (!t) throw new l("INVALID_CONFIG", `Pybara.checkout: "siteUrl" is not a valid http(s) URL: ${e.siteUrl}`);
370
- if (!e.siteName) throw new l("INVALID_CONFIG", "Pybara.checkout: \"siteName\" is required");
371
- if (e.currency != null && !/^[A-Z]{3}$/.test(e.currency)) throw new l("INVALID_CONFIG", `Pybara.checkout: "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(e.currency)}`);
372
- if (e.platform != null && !h.test(e.platform)) throw new l("INVALID_CONFIG", "Pybara.checkout: \"platform\" must be a lowercase slug (a-z, 0-9, -), at most 64 characters");
273
+ function h(e) {
274
+ if (!e.recipientPrincipal) throw new i("INVALID_CONFIG", "Pybara.checkout: \"recipientPrincipal\" is required");
275
+ if (!e.siteUrl) throw new i("INVALID_CONFIG", "Pybara.checkout: \"siteUrl\" is required");
276
+ let t = m(e.siteUrl);
277
+ if (!t) throw new i("INVALID_CONFIG", `Pybara.checkout: "siteUrl" is not a valid http(s) URL: ${e.siteUrl}`);
278
+ if (!e.siteName) throw new i("INVALID_CONFIG", "Pybara.checkout: \"siteName\" is required");
279
+ if (e.currency != null && !/^[A-Z]{3}$/.test(e.currency)) throw new i("INVALID_CONFIG", `Pybara.checkout: "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(e.currency)}`);
280
+ if (e.platform != null && !d.test(e.platform)) throw new i("INVALID_CONFIG", "Pybara.checkout: \"platform\" must be a lowercase slug (a-z, 0-9, -), at most 64 characters");
373
281
  return {
374
282
  ...e,
375
283
  siteUrl: t,
@@ -377,18 +285,18 @@ function y(e) {
377
285
  debug: e.debug ?? !1
378
286
  };
379
287
  }
380
- function b() {
288
+ function g() {
381
289
  let e = crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(16));
382
290
  return btoa(String.fromCharCode(...e));
383
291
  }
384
- function x(e) {
292
+ function _(e) {
385
293
  return e instanceof Error ? e : Error(String(e));
386
294
  }
387
295
  //#endregion
388
296
  //#region src/index.ts
389
- function S(e) {
390
- return new g(e);
297
+ function v(e) {
298
+ return new f(e);
391
299
  }
392
- var C = { checkout: S };
300
+ var y = { checkout: v };
393
301
  //#endregion
394
- export { C as Pybara, g as PybaraCheckout, l as PybaraError, S as checkout };
302
+ export { y as Pybara, f as PybaraCheckout, i as PybaraError, v as checkout };
package/dist/types.d.ts CHANGED
@@ -88,17 +88,19 @@ export interface PaymentParams {
88
88
  }
89
89
  /** The payment a button's createPayment() returns: open()'s params, without the callbacks, which buttons() takes itself. */
90
90
  export type ButtonPayment = Omit<PaymentParams, 'onSuccess' | 'onError' | 'onClose'>;
91
+ /**
92
+ * The served button's style, passed to it as given and read by it: `color` 'brand' | 'black' | 'white' (PayPal's names; its 'gold', 'blue' and 'silver' read as 'brand'), `shape` 'pill' | 'rect' | 'sharp', `height` 25–55 px (PayPal's range, default 45), and `borderRadius` in pixels, 0 or more, which overrides the shape's corners, as PayPal's.
93
+ * Copy a PayPal button's style and the two match. A value the button doesn't know falls back to its default.
94
+ */
95
+ export interface ButtonStyle {
96
+ color?: string;
97
+ shape?: string;
98
+ height?: number;
99
+ borderRadius?: number;
100
+ }
91
101
  /** Options for checkout.buttons(): a "Pybara" button, served by Pybara, that opens this checkout on click. */
92
102
  export interface ButtonsOptions {
93
- /**
94
- * Passed to the button as given, and read by it: `color` 'brand' | 'black' | 'white' (PayPal's names; its 'gold', 'blue' and 'silver' read as 'brand'), `shape` 'pill' | 'rect' | 'sharp', `height` 25–55 px (PayPal's range, default 45).
95
- * Copy a PayPal button's style and the two match. A value the button doesn't know falls back to its default.
96
- */
97
- style?: {
98
- color?: string;
99
- shape?: string;
100
- height?: number;
101
- };
103
+ style?: ButtonStyle;
102
104
  /** Collapse the button to no height when Pybara is unavailable on this page; by default its slot stays, empty, so the layout never moves. */
103
105
  hideWhenUnavailable?: boolean;
104
106
  /** Called on the payer's click: the payment from the form's current values, as open() takes it (amount, currency, frequency, donor fields). */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pybara/pybara-js",
3
- "version": "0.8.0",
3
+ "version": "0.9.1",
4
4
  "description": "Accept crypto payments and donations with Pybara on any page — a callable checkout, in the stripe-js / paypal-js convention.",
5
5
  "keywords": [
6
6
  "pybara",
@@ -32,6 +32,10 @@
32
32
  "types": "./dist/modal/index.d.ts",
33
33
  "import": "./dist/modal/index.js"
34
34
  },
35
+ "./button": {
36
+ "types": "./dist/button/index.d.ts",
37
+ "import": "./dist/button/index.js"
38
+ },
35
39
  "./dist/pybara-js.iife.js": "./dist/pybara-js.iife.js",
36
40
  "./package.json": "./package.json"
37
41
  },
@@ -43,7 +47,7 @@
43
47
  "build": "vite build && vite build -c vite.config.iife.ts",
44
48
  "prepare": "npm run build",
45
49
  "type-check": "tsc --noEmit",
46
- "prepublishOnly": "npm run type-check && npm run build",
50
+ "prepublishOnly": "npm run type-check && node scripts/check-readme-version.mjs && npm run build",
47
51
  "release:tag": "git tag v$npm_package_version && git push origin v$npm_package_version",
48
52
  "demo": "node demo/load-env.mjs && (sleep 1 && open http://localhost:5678 &) && npx serve demo -l 5678",
49
53
  "dev": "vite --open /demo/"
@@ -56,9 +60,5 @@
56
60
  "typescript": "7.0.2",
57
61
  "vite": "8.3.3",
58
62
  "vite-plugin-dts": "^5.1.2"
59
- },
60
- "repository": {
61
- "type": "git",
62
- "url": "git+https://github.com/pybara/pybara-js.git"
63
63
  }
64
64
  }
package/dist/buttons.d.ts DELETED
@@ -1,11 +0,0 @@
1
- import { Availability } from './modal/modal';
2
- import { ButtonsOptions, PaymentParams, PybaraButtons } from './types';
3
- /** What the loader needs from its checkout: the frame's origin, open(), and the availability answers. */
4
- export interface ButtonsHost {
5
- walletUrl: string;
6
- open(payment: PaymentParams): Promise<void>;
7
- /** Subscribes to every availability answer, first with the latest one if there is one; returns the unsubscribe. */
8
- subscribeAvailability(listener: (availability: Availability) => void): () => void;
9
- }
10
- export declare function createButtons(host: ButtonsHost, options: ButtonsOptions): PybaraButtons;
11
- //# sourceMappingURL=buttons.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"buttons.d.ts","sourceRoot":"","sources":["../src/buttons.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAe,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAEnG,yGAAyG;AACzG,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,mHAAmH;IACnH,qBAAqB,CAAC,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACnF;AAoBD,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,GAAG,aAAa,CAmGvF"}