@pybara/pybara-js 0.6.0 → 0.8.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.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Accept crypto payments and donations with **Pybara** on any page — a callable checkout, in the same convention as `@stripe/stripe-js` and `@paypal/paypal-js`.
4
4
 
5
- You keep your own UI — payment-method list, amount selector, form fields. `Pybara.checkout()` binds your site once and opens Pybara's own checkout surface (token selection, wallet, settlement, success screen) when the payer clicks.
5
+ You keep your own UI — payment-method list, amount selector, form fields. `Pybara.checkout()` binds your site once; `checkout.buttons()` draws a "Pybara" button beside your other payment methods, or `checkout.open()` opens Pybara's checkout from a button of your own. The checkout itself (wallet, token choice, settlement, success screen) is Pybara's.
6
6
 
7
7
  ## Install
8
8
 
@@ -13,14 +13,59 @@ 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://unpkg.com/@pybara/pybara-js/dist/pybara-js.iife.js"></script>
16
+ <script src="https://cdn.jsdelivr.net/npm/@pybara/pybara-js@0.7/dist/pybara-js.iife.js"></script>
17
17
  <script>
18
- const pybara = Pybara.checkout({ siteUrl, siteName, recipientPrincipal });
19
- // await pybara.open({ amount: '100', currency: 'EUR' }) on click — identical to the ESM surface
18
+ const pybara = Pybara.checkout({ siteUrl, siteName, recipientPrincipal, currency: 'EUR' });
19
+ pybara.buttons({ createPayment: () => ({ amount: '25' }) }).render('#pybara-button');
20
20
  </script>
21
21
  ```
22
22
 
23
- ## Add Pybara as a payment method
23
+ ## Add Pybara next to PayPal
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:
26
+
27
+ ```html
28
+ <div id="paypal-button-container"></div>
29
+ <div id="pybara-button"></div>
30
+ ```
31
+
32
+ ```ts
33
+ import { Pybara } from '@pybara/pybara-js';
34
+
35
+ const pybara = Pybara.checkout({
36
+ siteUrl: 'https://example.com', // this site, as registered in Pybara Wallet
37
+ siteName: 'Example Org',
38
+ recipientPrincipal: 'aaaaa-bbbbb-…', // the site owner's wallet principal (see "Before it works")
39
+ currency: 'EUR',
40
+ });
41
+
42
+ pybara.buttons({
43
+ style: { color: 'black', shape: 'rect', height: 45 }, // the same style as the PayPal button
44
+ createPayment: () => ({ amount: amountInput.value }), // read on the click; add frequency: 'monthly' for a subscription
45
+ onStateChange: ({ message }) => (hint.textContent = message ?? ''), // e.g. "Minimum €0.70", in the payer's language
46
+ onSuccess: (result) => showThanks(result),
47
+ }).render('#pybara-button');
48
+
49
+ amountInput.addEventListener('input', () => pybara.precheck({ amount: amountInput.value }));
50
+ ```
51
+
52
+ - **The button follows availability by itself:** disabled below the minimum, and its slot left empty when Pybara can't be used on this page yet. It holds no text but "Pybara"; the page around it says what it's for.
53
+ - **One-time and monthly side by side:** call `buttons()` twice on the same checkout, one with `frequency: 'monthly'`.
54
+ - **Everything the payer sees is served by Pybara,** so the button stays current without updating this package.
55
+
56
+ ## Before it works: the site owner's steps
57
+
58
+ Code can't do these; whoever adds Pybara to the site relays them to the site owner, once:
59
+
60
+ > 1. Create a Pybara Wallet at <https://pybara.io>, then open **Manage › Sites › Add a site without a plugin** and enter this site's address.
61
+ > 2. Publish the DNS `TXT` record the wallet shows (`_pybara-payto`, holding the wallet's principal) with the domain's DNS provider, until the wallet shows **Verified**.
62
+ > 3. Accept the widget terms for the site there, and copy the wallet's principal into `recipientPrincipal`.
63
+ >
64
+ > Until then the Pybara button stays hidden, and the browser console says which step is missing. It works on the site's registered domain, not on a preview URL.
65
+
66
+ Full guide: <https://docs.pybara.com/pybara-js/setup/>
67
+
68
+ ## Or your own button: `open()`
24
69
 
25
70
  ```ts
26
71
  import { Pybara } from '@pybara/pybara-js';
@@ -33,7 +78,7 @@ const pybara = Pybara.checkout({
33
78
  currency: 'EUR', // optional default for open(); one currency per site
34
79
  });
35
80
 
36
- // On your "Pybara" payment-option click — opens the checkout over your page:
81
+ // On your own button's click — opens the checkout over your page:
37
82
  await pybara.open({
38
83
  amount: '100', // in EUR, as a decimal string: '12.34', '1000' for JPY
39
84
  donorEmail: 'laurens@example.org', // optional — enables the receipt email + tax receipts
@@ -52,10 +97,6 @@ await pybara.open({ amount: '25', frequency: 'monthly', durationMonths: 12 });
52
97
  // omit durationMonths for an open-ended subscription
53
98
  ```
54
99
 
55
- ## One human step
56
-
57
- The code above is all an AI builder needs. The one thing code can't do: the site owner registers the site in **Pybara Wallet** (Manage › Sites → *Add a site without a plugin*), publishes the `_pybara-payto` DNS record it gives you, and accepts the widget terms — a one-time, two-minute step. Full guide: <https://docs.pybara.com/donate-widget/overview/>
58
-
59
100
  ## Reference
60
101
 
61
102
  ### `Pybara.checkout(config)` → `PybaraCheckout`
@@ -92,6 +133,18 @@ The code above is all an AI builder needs. The one thing code can't do: the site
92
133
  | `onSuccess(result)` | `function` | Payment confirmed — `result` carries block height, token, principals |
93
134
  | `onError(err)` `onClose()` | `function` | Checkout refusals (`EmbeddedError`, `err.code`) / modal closed |
94
135
 
136
+ ### `checkout.buttons(options)` → `{ render(el), destroy() }`
137
+
138
+ | Field | Type | Description |
139
+ |---|---|---|
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 |
142
+ | `hideWhenUnavailable` | `boolean` | Collapse the button instead of leaving its slot empty when Pybara is unavailable |
143
+ | `onStateChange(availability)` | `function` | The checkout's availability answer, once per answer — see [Availability](#availability) |
144
+ | `onSuccess(result)` `onError(err)` `onClose()` | `function` | As `open()`'s |
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.
147
+
95
148
  ### Availability
96
149
 
97
150
  With `onAvailability` set, Pybara tells the page — before any click — whether a payment would go through, so you show the option only when it works:
@@ -126,6 +179,8 @@ amountInput.addEventListener('input', () => pybara.precheck({ amount: amountInpu
126
179
 
127
180
  Once open, the checkout reports a refusal to `onError` as an `EmbeddedError`, also with `err.code`. The ones an integration can cause: `INVALID_CHECKOUT` (the message names the field and what it must be, e.g. `checkout.amount "12.345" has more decimals than EUR has (2)`) and `RATE_UNAVAILABLE` (Pybara's rate for the currency couldn't be loaded — let the payer try again). An amount below the minimum isn't an error: the checkout shows the minimum itself.
128
181
 
182
+ If pybara.io can't be reached, the checkout doesn't spin forever: after 15 seconds without its first screen it says it couldn't load, with **Try again** and **Close**, and closing reports `FRAME_UNAVAILABLE` to `onError`, so the page can offer another way to pay. A `buttons()` button that doesn't load in that time leaves its slot empty and reports `unavailable` to `onStateChange`.
183
+
129
184
  ## Scope
130
185
 
131
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.
@@ -145,6 +145,30 @@
145
145
  "onError": { "description": "function (Error) => void — called on frame-level errors; not expressible in JSON." },
146
146
  "onClose": { "description": "function () => void — called when the payer closes the checkout; not expressible in JSON." }
147
147
  }
148
+ },
149
+ "buttons": {
150
+ "title": "checkout.buttons(options)",
151
+ "description": "A 'Pybara' button, served by Pybara, that opens this checkout on the payer's click. Draw it with .render(element or selector), as often as wanted; .destroy() removes them. Its look follows availability by itself; call checkout.precheck({ amount, currency }) when the form changes.",
152
+ "type": "object",
153
+ "additionalProperties": false,
154
+ "required": ["createPayment"],
155
+ "properties": {
156
+ "style": {
157
+ "type": "object",
158
+ "description": "Passed to the button as given. Copy a PayPal button's style and the two match.",
159
+ "properties": {
160
+ "color": { "type": "string", "description": "'brand' | 'black' | 'white' (PayPal's names; its 'gold', 'blue', 'silver' read as 'brand'). Default 'brand'." },
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." }
163
+ }
164
+ },
165
+ "hideWhenUnavailable": { "type": "boolean", "description": "Collapse the button to no height when Pybara is unavailable here; by default its slot stays, empty." },
166
+ "createPayment": { "description": "function () => payment | Promise<payment> — called on the click: the payment from the form's current values, as open() takes it (amount, currency, frequency, donor fields), without callbacks; not expressible in JSON." },
167
+ "onStateChange": { "description": "function (Availability) => void — the checkout's availability answer, once per answer; e.g. show availability.message below the minimum. Not expressible in JSON." },
168
+ "onSuccess": { "description": "function (CheckoutResult) => void — the payment is confirmed on-chain; not expressible in JSON." },
169
+ "onError": { "description": "function (Error) => void — a refusal from createPayment(), open() or the checkout; not expressible in JSON." },
170
+ "onClose": { "description": "function () => void — the payer closed the checkout; not expressible in JSON." }
171
+ }
148
172
  }
149
173
  }
150
174
  }
@@ -0,0 +1,11 @@
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
@@ -0,0 +1 @@
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"}
@@ -1,5 +1,5 @@
1
1
  import { WidgetGate } from './gate';
2
- import { CheckoutConfig, PaymentParams } from './types';
2
+ import { ButtonsOptions, CheckoutConfig, PaymentParams, PybaraButtons } from './types';
3
3
  /**
4
4
  * A bound checkout — what Pybara.checkout() returns.
5
5
  *
@@ -20,7 +20,18 @@ export declare class PybaraCheckout {
20
20
  readonly ready: Promise<void>;
21
21
  /** The latest precheck()'s amount and currency, sent again to each rebuilt checkout frame. */
22
22
  private lastPrecheck;
23
+ /** Every listener for availability answers: the config's onAvailability, and each rendered button. */
24
+ private readonly availabilityListeners;
25
+ /** The latest answer, handed to a listener as it subscribes. */
26
+ private latestAvailability;
23
27
  constructor(userConfig: CheckoutConfig);
28
+ /**
29
+ * A "Pybara" button, served by Pybara, that opens this checkout on the payer's click with the payment createPayment() returns.
30
+ * Its look follows availability by itself (disabled below the minimum, hidden when Pybara can't be used here); call precheck({ amount }) as the form changes.
31
+ * Render it as often as wanted, e.g. a one-time and a monthly button side by side: they share this one checkout.
32
+ */
33
+ buttons(options: ButtonsOptions): PybaraButtons;
34
+ private emitAvailability;
24
35
  /**
25
36
  * Ask whether a payment of this amount would go through right now; the answer arrives on the config's onAvailability.
26
37
  * Call it again whenever the form's amount or currency changes: only the latest is answered.
@@ -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;AAC1D,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,aAAa,EAEnB,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;gBAEtD,UAAU,EAAE,cAAc;IAOtC;;;;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;IAmB1B,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;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"}
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 CheckoutConfig, type CheckoutResult, type Frequency, type PaymentParams, PybaraError, type PybaraErrorCode, } from './types';
14
+ export { type ButtonPayment, type ButtonsOptions, 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,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,WAAW,EACX,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,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,SAAS,CAAC"}
@@ -15,5 +15,13 @@ export declare const MODAL_MOTION: {
15
15
  /** The backdrop starts fading this long after the panel, for a layered close. */
16
16
  OVERLAY_FADE_OUT_DELAY_MS: number;
17
17
  OVERLAY_FADE_OUT_MS: number;
18
+ /** The frame's height follows each step: short and decelerating, so a step change settles quickly, as the frame may resize several times per checkout. */
19
+ RESIZE_MS: number;
20
+ RESIZE_EASING: string;
18
21
  };
22
+ /**
23
+ * How long the checkout may take to show its first screen after show(), and a button to report ready after render(), before they are treated as unreachable.
24
+ * The frame is preloaded hidden, so this is usually extra time on top of a load that started long before; a frame that is up answers in about a second.
25
+ */
26
+ export declare const FRAME_LOAD_TIMEOUT_MS = 15000;
19
27
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/modal/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,cAAc;;;CAG1B,CAAC;AAEF,gHAAgH;AAChH,eAAO,MAAM,YAAY;;IAExB,oFAAoF;;IAEpF,qDAAqD;;IAErD,iFAAiF;;;CAGjF,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/modal/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,cAAc;;;CAG1B,CAAC;AAEF,gHAAgH;AAChH,eAAO,MAAM,YAAY;;IAExB,oFAAoF;;IAEpF,qDAAqD;;IAErD,iFAAiF;;;IAGjF,0JAA0J;;;CAG1J,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAQ,CAAC"}
@@ -1 +1 @@
1
- export { t as CheckoutModal, n as EmbeddedError } from "../modal-CvQ7qr5d.js";
1
+ export { t as CheckoutModal, n as EmbeddedError } from "../modal-BiPk8xwF.js";
@@ -182,12 +182,13 @@ export interface Checkout {
182
182
  declare const EMBEDDED_ERROR_CODES: readonly ["DESTINATION_REFUSED", "INVALID_BENEFICIARY", "INVALID_CHECKOUT", "NO_WALLET_AVAILABLE", "RATE_UNAVAILABLE", "SITE_MISMATCH"];
183
183
  type EmbeddedErrorCode = typeof EMBEDDED_ERROR_CODES[number];
184
184
  /**
185
- * The error handed to onError() when the frame refuses.
185
+ * The error handed to onError() when the frame refuses, or when it never loaded.
186
186
  * Carries `.code` so a platform branches on it rather than string-matching `.message`, which may be reworded or localised at any time.
187
+ * FRAME_UNAVAILABLE is this package's own: the checkout showed nothing within FRAME_LOAD_TIMEOUT_MS of show() and the buyer closed the message saying so; the page may offer another payment method.
187
188
  */
188
189
  export declare class EmbeddedError extends Error {
189
- readonly code: EmbeddedErrorCode | 'UNKNOWN';
190
- constructor(code: EmbeddedErrorCode | 'UNKNOWN', message: string);
190
+ readonly code: EmbeddedErrorCode | 'FRAME_UNAVAILABLE' | 'UNKNOWN';
191
+ constructor(code: EmbeddedErrorCode | 'FRAME_UNAVAILABLE' | 'UNKNOWN', message: string);
191
192
  }
192
193
  export declare class CheckoutModal {
193
194
  private config;
@@ -204,11 +205,30 @@ export declare class CheckoutModal {
204
205
  private iframeLoaded;
205
206
  /** Held by show() when it runs before `load`; the `load` handler sends it. */
206
207
  private pendingPaymentData;
208
+ /** The last show()'s data, sent again when the buyer retries a frame that never loaded. */
209
+ private lastPaymentData;
210
+ /** Runs from show() until the frame's first screen; when it fires, the checkout is unreachable (FRAME_LOAD_TIMEOUT_MS). */
211
+ private loadTimer;
212
+ /** The "couldn't load" message, while it is up. */
213
+ private unavailableBox;
207
214
  /** Held by precheck() when it runs before `load`; the `load` handler sends the latest. */
208
215
  private pendingPrecheck;
209
216
  constructor(config: CheckoutModalConfig);
210
217
  /** Backdrop and iframe, built at construction and hidden until open() — see the file header for why. */
211
218
  private createIframe;
219
+ private onIframeLoad;
220
+ private clearLoadTimer;
221
+ /** From show(), until the frame's first screen: no screen within FRAME_LOAD_TIMEOUT_MS means pybara.io could not be reached, and the buyer is told so rather than left with a spinner. */
222
+ private startLoadTimer;
223
+ /**
224
+ * In place of the spinner: the checkout could not load, with Try again (reloading the frame) and Close (which reports FRAME_UNAVAILABLE to onError).
225
+ * In English: the frame, which holds the checkout's twelve languages, is exactly what failed to arrive.
226
+ */
227
+ private renderUnavailable;
228
+ /** Reload the frame and send it the last checkout again, with the spinner back and a fresh timeout. */
229
+ private retryLoad;
230
+ /** The buyer gave up on a frame that never loaded: the modal closes and the page hears why, so it can offer another way to pay. */
231
+ private closeUnavailable;
212
232
  /**
213
233
  * Ask the frame whether a payment would go through right now; the answer arrives on onAvailability.
214
234
  * Send it again whenever the amount changes: the frame answers the latest, at a rate it sets.
@@ -1 +1 @@
1
- {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../src/modal/modal.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../src/modal/modal.ts"],"names":[],"mappings":"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"}
@@ -8,15 +8,17 @@ var e = {
8
8
  PANEL_OPEN_MS: 300,
9
9
  PANEL_CLOSE_MS: 200,
10
10
  OVERLAY_FADE_OUT_DELAY_MS: 50,
11
- OVERLAY_FADE_OUT_MS: 150
12
- }, n = 0, r = 0, i = 0;
13
- function a(e) {
14
- e.preventDefault();
15
- }
11
+ OVERLAY_FADE_OUT_MS: 150,
12
+ RESIZE_MS: 600,
13
+ RESIZE_EASING: ""
14
+ }, n = 15e3, r = 0, i = 0, a = 0;
16
15
  function o(e) {
17
16
  e.preventDefault();
18
17
  }
19
18
  function s(e) {
19
+ e.preventDefault();
20
+ }
21
+ function c(e) {
20
22
  e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement || [
21
23
  "ArrowUp",
22
24
  "ArrowDown",
@@ -27,21 +29,21 @@ function s(e) {
27
29
  " "
28
30
  ].includes(e.key) && e.preventDefault();
29
31
  }
30
- function c() {
31
- window.scrollTo(r, i);
32
- }
33
32
  function l() {
34
- n === 0 && (r = window.scrollX, i = window.scrollY, window.addEventListener("wheel", a, { passive: !1 }), window.addEventListener("touchmove", o, { passive: !1 }), window.addEventListener("keydown", s), window.addEventListener("scroll", c)), n += 1;
33
+ window.scrollTo(i, a);
35
34
  }
36
35
  function u() {
37
- n !== 0 && (--n, n === 0 && (window.removeEventListener("wheel", a), window.removeEventListener("touchmove", o), window.removeEventListener("keydown", s), window.removeEventListener("scroll", c)));
36
+ 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;
37
+ }
38
+ function d() {
39
+ r !== 0 && (--r, r === 0 && (window.removeEventListener("wheel", o), window.removeEventListener("touchmove", s), window.removeEventListener("keydown", c), window.removeEventListener("scroll", l)));
38
40
  }
39
41
  //#endregion
40
42
  //#region src/modal/modal.ts
41
- function d() {
43
+ function f() {
42
44
  return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
43
45
  }
44
- var f = [
46
+ var p = [
45
47
  "DESTINATION_REFUSED",
46
48
  "INVALID_BENEFICIARY",
47
49
  "INVALID_CHECKOUT",
@@ -49,20 +51,20 @@ var f = [
49
51
  "RATE_UNAVAILABLE",
50
52
  "SITE_MISMATCH"
51
53
  ];
52
- function p(e) {
53
- return f.includes(e) ? e : "UNKNOWN";
54
+ function m(e) {
55
+ return p.includes(e) ? e : "UNKNOWN";
54
56
  }
55
- var m = class extends Error {
57
+ var h = class extends Error {
56
58
  constructor(e, t) {
57
59
  super(t), this.name = "EmbeddedError", this.code = e, Object.setPrototypeOf(this, new.target.prototype);
58
60
  }
59
61
  };
60
- function h(e) {
62
+ function g(e) {
61
63
  return typeof e == "object" && !!e && typeof e.type == "string" && e.type.startsWith("pybara_embedded_");
62
64
  }
63
- var g = class {
65
+ var _ = class {
64
66
  constructor(e) {
65
- 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.pendingPrecheck = null, this.config = e, this.walletOrigin = new URL(e.walletUrl).origin, this.createIframe();
67
+ 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();
66
68
  }
67
69
  createIframe() {
68
70
  let n = document.createElement("div");
@@ -86,10 +88,8 @@ var g = class {
86
88
  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)" }], {
87
89
  duration: 1e3,
88
90
  iterations: Infinity
89
- }), r.addEventListener("load", () => {
90
- this.iframeLoaded = !0, this.pendingPrecheck &&= (this.sendPrecheck(this.pendingPrecheck), null), this.pendingPaymentData &&= (this.sendInitMessage(this.pendingPaymentData), null);
91
- }, { once: !0 }), this.handleMessage = (e) => {
92
- if (e.origin === this.walletOrigin && e.source === r.contentWindow && h(e.data)) switch (e.data.type) {
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) {
93
93
  case "pybara_embedded_result":
94
94
  this.config.onSuccess?.({
95
95
  blockIndex: e.data.blockIndex,
@@ -99,13 +99,13 @@ var g = class {
99
99
  });
100
100
  break;
101
101
  case "pybara_embedded_error":
102
- this.close(), this.config.onError?.(new m(p(e.data.code), e.data.message));
102
+ this.close(), this.config.onError?.(new h(m(e.data.code), e.data.message));
103
103
  break;
104
104
  case "pybara_embedded_closed":
105
105
  this.close(), this.config.onClose?.();
106
106
  break;
107
107
  case "pybara_embedded_resize":
108
- r.style.height !== `${e.data.height}px` && (r.style.height = `${e.data.height}px`), this.spinner && (this.spinner.remove(), this.spinner = null, d() || r.animate([{
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([{
109
109
  transform: "translateY(20px)",
110
110
  opacity: 0
111
111
  }, {
@@ -114,7 +114,7 @@ var g = class {
114
114
  }], {
115
115
  duration: t.PANEL_OPEN_MS,
116
116
  easing: "ease"
117
- }));
117
+ }), r.offsetHeight, r.style.transition = `height ${t.RESIZE_MS}ms ${t.RESIZE_EASING}`));
118
118
  break;
119
119
  case "pybara_embedded_closable":
120
120
  this.closable = e.data.closable;
@@ -126,9 +126,39 @@ var g = class {
126
126
  }
127
127
  }
128
128
  }, window.addEventListener("message", this.handleMessage), this.handleEscapeKey = (e) => {
129
- e.key === "Escape" && this.closable && (this.close(), this.config.onClose?.());
129
+ e.key === "Escape" && this.closable && (this.unavailableBox ? this.closeUnavailable() : (this.close(), this.config.onClose?.()));
130
130
  }, document.addEventListener("keydown", this.handleEscapeKey), n.appendChild(i), n.appendChild(r), document.body.appendChild(n), this.overlay = n, this.iframe = r, this.spinner = i;
131
131
  }
132
+ onIframeLoad() {
133
+ this.iframeLoaded = !0, this.pendingPrecheck &&= (this.sendPrecheck(this.pendingPrecheck), null), this.pendingPaymentData &&= (this.sendInitMessage(this.pendingPaymentData), null);
134
+ }
135
+ clearLoadTimer() {
136
+ this.loadTimer !== null && (clearTimeout(this.loadTimer), this.loadTimer = null);
137
+ }
138
+ startLoadTimer() {
139
+ this.clearLoadTimer(), this.spinner && (this.loadTimer = setTimeout(() => {
140
+ this.loadTimer = null, this.renderUnavailable();
141
+ }, n));
142
+ }
143
+ renderUnavailable() {
144
+ if (!this.overlay || this.unavailableBox) return;
145
+ this.spinner && (this.spinner.style.display = "none");
146
+ let e = document.createElement("div");
147
+ 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 ";
148
+ let t = document.createElement("p");
149
+ t.style.cssText = "margin: 0 0 1.25rem;", t.textContent = "The checkout couldn't load. Check your connection and try again.";
150
+ let n = "font: inherit; padding: 0.55rem 1.2rem; border-radius: 8px; cursor: pointer; margin: 0 0.3rem;", r = document.createElement("button");
151
+ r.type = "button", r.textContent = "Try again", r.style.cssText = `${n} background: #111827; color: #fff; border: 1px solid #111827;`, r.addEventListener("click", () => this.retryLoad());
152
+ let i = document.createElement("button");
153
+ 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();
154
+ }
155
+ retryLoad() {
156
+ let e = this.iframe;
157
+ 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());
158
+ }
159
+ closeUnavailable() {
160
+ this.close(), this.config.onError?.(new h("FRAME_UNAVAILABLE", `The Pybara checkout (${this.walletOrigin}/pay) did not load within ${n / 1e3} seconds.`));
161
+ }
132
162
  precheck(e) {
133
163
  this.iframeLoaded ? this.sendPrecheck(e) : this.pendingPrecheck = e;
134
164
  }
@@ -155,16 +185,16 @@ var g = class {
155
185
  this.iframe?.contentWindow?.postMessage(t, this.walletOrigin);
156
186
  }
157
187
  open() {
158
- this.overlay && this.overlay.style.display !== "flex" && (l(), this.overlay.style.display = "flex", d() || this.overlay.animate([{ opacity: 0 }, { opacity: 1 }], {
188
+ this.overlay && this.overlay.style.display !== "flex" && (u(), this.overlay.style.display = "flex", f() || this.overlay.animate([{ opacity: 0 }, { opacity: 1 }], {
159
189
  duration: t.OVERLAY_FADE_IN_MS,
160
190
  easing: "ease"
161
191
  }));
162
192
  }
163
193
  show(e) {
164
- this.open(), this.iframeLoaded ? this.sendInitMessage(e) : this.pendingPaymentData = e;
194
+ this.open(), this.lastPaymentData = e, this.startLoadTimer(), this.iframeLoaded ? this.sendInitMessage(e) : this.pendingPaymentData = e;
165
195
  }
166
196
  renderTerminalState(t) {
167
- this.close(), l();
197
+ this.close(), u();
168
198
  let n = document.createElement("div");
169
199
  n.className = "pybara-checkout-overlay", n.style.cssText = `
170
200
  position: fixed;
@@ -181,13 +211,13 @@ var g = class {
181
211
  `;
182
212
  let r = document.createElement("div");
183
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) => {
184
- e.target === n && (n.remove(), u(), this.config.onClose?.());
214
+ e.target === n && (n.remove(), d(), this.config.onClose?.());
185
215
  }), document.body.appendChild(n), this.overlay = n;
186
216
  }
187
217
  close() {
188
- this.handleMessage &&= (window.removeEventListener("message", this.handleMessage), null), this.handleEscapeKey &&= (document.removeEventListener("keydown", this.handleEscapeKey), null), u();
218
+ this.handleMessage &&= (window.removeEventListener("message", this.handleMessage), null), this.handleEscapeKey &&= (document.removeEventListener("keydown", this.handleEscapeKey), null), d();
189
219
  let e = this.overlay, n = this.iframe;
190
- this.overlay = null, this.iframe = null, this.spinner = null, this.iframeLoaded = !1, this.pendingPaymentData = null, this.pendingPrecheck = null, this.closable = !0, e && (e.style.display === "none" || d() ? e.remove() : (e.style.pointerEvents = "none", n?.animate([{
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([{
191
221
  transform: "scale(1)",
192
222
  opacity: 1
193
223
  }, {
@@ -206,4 +236,4 @@ var g = class {
206
236
  }
207
237
  };
208
238
  //#endregion
209
- export { m as n, g as t };
239
+ export { h as n, n as r, _ as t };