@amos.com/react-amos-js 0.10.5 → 0.11.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
@@ -15,8 +15,8 @@ npm install @amos.com/react-amos-js @amos.com/node
15
15
  ## What it gives you
16
16
 
17
17
  - React components for the iframe payment method forms: `AmosCreditCardPaymentMethodForm`, `AmosBankAccountPaymentMethodForm`, `AmosGooglePayButton`, `AmosApplePayButton`.
18
- - React-flavoured iframe message helpers that accept a React `ref`: `validateForm({ iframeRef })`, `confirmPaymentIntent({ iframeRef, token })`, `confirmSetupIntent({ iframeRef, token })`, `resetForm({ iframeRef })`.
19
- - Re-exports of the `@amos.com/amos-js` helpers and types that come up in client code: `createMessage`, `decodeJwt`, `getEmbedOrigin`, `formatGooglePayPaymentData`, `resetForm`, `ConfirmationResult`, `ConfirmationIncompleteReason`, `FormattedGooglePayPaymentData`, `Appearance`, `Message`, etc.
18
+ - React-flavoured iframe message helpers that accept a React `ref`: `validateForm({ iframeRef })`, `confirmPayment({ iframeRef, token })`, `confirmSetup({ iframeRef, token })`, `resetForm({ iframeRef })`.
19
+ - Re-exports of the `@amos.com/amos-js` helpers and types that come up in client code: `createMessage`, `decodeJwt`, `getEmbedOrigin`, `formatGooglePayPaymentData`, `resetForm`, `ConfirmResult`, `ConfirmationResult`, `ConfirmationIncompleteReason`, `FormattedGooglePayPaymentData`, `Appearance`, `Message`, etc.
20
20
 
21
21
  > **Note:** `@amos.com/react-amos-js` is the client-side half of the Amos integration. For end-to-end payment processing you also need `@amos.com/node` on your server (creating payment intents, handling webhooks, etc.). The same `@amos.com/node` package is listed as a peer dependency so you can import its OpenAPI types in client-side TypeScript code.
22
22
 
@@ -39,12 +39,12 @@ The render token configures the iframe's allowed origin(s), allowed payment meth
39
39
  The following flow is for credit card and bank account payment method types only.
40
40
 
41
41
  1. **Set up prerequisites**: create a `renderToken` (safe for client), and keep `apiKey` and `accountId` server-side only.
42
- 2. **Render your checkout UI** with one of the payment method components (e.g. `AmosCreditCardPaymentMethodForm`) along with the required `onResult` prop. Card and bank forms show a field-shaped skeleton immediately (sized from `appearance`, `additionalFields`, and `billingAddressRequirement`); Google Pay and Apple Pay paint a button-shaped skeleton in the parent document on first render so the 48px slot is reserved before the iframe loads.
42
+ 2. **Render your checkout UI** with one of the payment method components (e.g. `AmosCreditCardPaymentMethodForm`). Card and bank forms show a field-shaped skeleton immediately (sized from `appearance`, `additionalFields`, and `billingAddressRequirement`); Google Pay and Apple Pay paint a button-shaped skeleton in the parent document on first render so the 48px slot is reserved before the iframe loads.
43
43
  3. **User clicks "Pay now" button**: call `validateForm({ iframeRef })`, which returns `Promise<true>` if the embedded form is valid and `Promise<false>` otherwise.
44
44
  4. **Create payment intent on your server**: use your server-side Amos client to call `POST /payment_intents`. You may also associate this payment intent with a new or existing customer via `POST /customers`. This must be server-side because it uses your private API key.
45
45
  5. **Return the payment intent token to the browser**: your backend responds with the embed token (`components["schemas"]["EmbedToken"]`) needed for confirmation.
46
- 6. **Confirm the payment intent from the client**: call `confirmPaymentIntent({ iframeRef, token })` to continue the payment flow.
47
- 7. **Handle UX**: show the user a "processing" state when the "Pay now" button is clicked, and handle `onResult`. Do not treat `onResult` as settlement proof — verify payment success on your backend via webhooks. Recoverable field errors are shown in the iframe (`status: "incomplete"` with `reason`: `"field_errors"` or `"validation_failed"`).
46
+ 6. **Confirm the payment intent from the client**: `await confirmPayment({ iframeRef, token })`. Deprecated alias: `confirmPaymentIntent`.
47
+ 7. **Handle UX**: show the user a "processing" state while awaiting `confirmPayment`. Do not treat `{ status: "succeeded" }` as settlement proof — verify payment success on your backend via webhooks. Recoverable field errors stay in the iframe; `confirmPayment` still resolves `{ status: "failed" }`. Legacy hosts can keep optional `onResult`.
48
48
 
49
49
  ### Google Pay & Apple Pay
50
50
 
@@ -52,17 +52,17 @@ Google Pay and Apple Pay are forms of express checkout. Their buttons are altern
52
52
 
53
53
  The key differences between the express and non-express payment flows are:
54
54
 
55
- - The express payment method components accept a prop called `onInitiatePaymentIntentRequest` which will be called when you should create the payment intent on your server.
55
+ - The express payment method components accept `onConfirm`. Create a payment intent, then `await confirmPayment(token)`.
56
56
  - You do not call `validateForm` in an express flow.
57
- - You do not call `confirmPaymentIntent` in an express flow (this is done after `onInitiatePaymentIntentRequest` returns a token).
57
+ - You call `confirmPayment` inside `onConfirm` (the SDK no longer auto-confirms).
58
58
 
59
59
  ## Understanding the flow for creating and confirming setup intents
60
60
 
61
61
  Setup intents are used to save payment methods for future use (e.g. recurring payments, subscriptions) without charging the customer immediately. The flow is identical to a payment intent, except:
62
62
 
63
63
  - On the server, call `POST /setup_intents` instead of `POST /payment_intents`.
64
- - On the client, call `confirmSetupIntent({ iframeRef, token })` instead of `confirmPaymentIntent({ iframeRef, token })`.
65
- - The same `onResult` callback is used; succeeded setup intents arrive as `{ status: "succeeded", intent: "setup", setupIntent }`.
64
+ - On the client, `await confirmSetup({ iframeRef, token })` instead of `confirmPayment({ iframeRef, token })`. Deprecated alias: `confirmSetupIntent`.
65
+ - Both resolve `{ status: "succeeded" | "failed" }`.
66
66
 
67
67
  The same `AmosCreditCardPaymentMethodForm` / `AmosBankAccountPaymentMethodForm` components support both payment intents and setup intents — they are differentiated by which confirmation function you call. For bank setup, pass `intent="setup"` so Connect / Plaid is always shown (no merchant ACH threshold lookup).
68
68
 
@@ -75,8 +75,8 @@ Why this matters:
75
75
  - The payment method UI is rendered inside Amos-hosted iframes, so sensitive input fields are not part of your DOM.
76
76
  - Raw payment details are submitted from the iframe directly to Amos-controlled infrastructure.
77
77
  - Your backend only creates payment intents (or setup intents) and returns a short-lived token used to continue the iframe flow.
78
- - `confirmPaymentIntent` / `confirmSetupIntent` sends the token back to the iframe to complete confirmation; it does not pass full payment method payloads through your app server.
79
- - In express flows (Google Pay / Apple Pay), the iframe component handles payment data exchange and only asks your server to create a payment intent token.
78
+ - `confirmPayment` / `confirmSetup` send the token back to the iframe to complete confirmation; they do not pass full payment method payloads through your app server.
79
+ - In express flows (Google Pay / Apple Pay), the iframe handles payment data exchange and calls `onConfirm` so your server can create a payment intent token, then you `await confirmPayment(token)`.
80
80
 
81
81
  In short, your app orchestrates the payment flow, while sensitive payment data stays within Amos-controlled components and APIs.
82
82
 
@@ -94,10 +94,6 @@ Card and bank components accept an optional `appearance` prop that controls the
94
94
  "--radius": "0.25rem",
95
95
  },
96
96
  }}
97
- onResult={(result) => {
98
- if (result.status === "failed") setError(result.errorMessage);
99
- if (result.status === "incomplete") setError(null);
100
- }}
101
97
  />
102
98
  ```
103
99
 
@@ -167,7 +163,7 @@ Radio groups (e.g. account type) always use an above-style group label regardles
167
163
  import { useRef, useState } from "react";
168
164
  import {
169
165
  AmosCreditCardPaymentMethodForm,
170
- confirmPaymentIntent,
166
+ confirmPayment,
171
167
  validateForm,
172
168
  } from "@amos.com/react-amos-js";
173
169
  import type { components } from "@amos.com/node";
@@ -212,7 +208,10 @@ function CheckoutForm() {
212
208
  }
213
209
 
214
210
  const { token } = await response.json();
215
- confirmPaymentIntent({ iframeRef, token });
211
+ const result = await confirmPayment({ iframeRef, token });
212
+ if (result.status !== "succeeded") {
213
+ setError("Payment failed. Please try again.");
214
+ }
216
215
  } catch (error) {
217
216
  setError(error instanceof Error ? error.message : "Unknown error");
218
217
  } finally {
@@ -227,16 +226,6 @@ function CheckoutForm() {
227
226
  renderToken="the-render-token-that-you-created-on-dashboard.amos.com"
228
227
  additionalFields={{ cardholderName: true }}
229
228
  onValidityChange={({ isValid }) => setIsValid(isValid)}
230
- onResult={(result) => {
231
- // Unlock UI. Verify settlement on your backend via webhooks.
232
- if (result.status === "succeeded") {
233
- console.log("Confirm returned:", result);
234
- } else if (result.status === "failed") {
235
- console.error("Confirm failed:", result.errorMessage);
236
- } else if (result.status === "incomplete") {
237
- console.log("Recoverable:", result.reason);
238
- }
239
- }}
240
229
  />
241
230
  {error ? <p>{error}</p> : null}
242
231
  <button type="submit" disabled={!isValid || isProcessing}>
@@ -254,7 +243,7 @@ import { useState } from "react";
254
243
  import {
255
244
  AmosApplePayButton,
256
245
  AmosGooglePayButton,
257
- type ConfirmationResult,
246
+ type ConfirmResult,
258
247
  } from "@amos.com/react-amos-js";
259
248
  import type { components } from "@amos.com/node";
260
249
 
@@ -283,13 +272,28 @@ async function createPaymentIntentToken({
283
272
  function CheckoutWallets({ renderToken }: { renderToken: string }) {
284
273
  const [error, setError] = useState<string | null>(null);
285
274
 
286
- function handleResult(result: ConfirmationResult) {
287
- if (result.status === "succeeded") {
288
- console.log("Confirm returned:", result);
289
- } else if (result.status === "failed") {
290
- setError(result.errorMessage);
291
- } else if (result.status === "incomplete") {
292
- console.log("Recoverable:", result.reason);
275
+ async function handleConfirm({
276
+ paymentIntentCreateAttributes,
277
+ customerCreateAttributes,
278
+ confirmPayment,
279
+ }: {
280
+ paymentIntentCreateAttributes: components["schemas"]["CreatePaymentIntentInput"];
281
+ customerCreateAttributes: components["schemas"]["CreateCustomerInput"];
282
+ confirmPayment: (token: string) => Promise<ConfirmResult>;
283
+ }): Promise<ConfirmResult> {
284
+ try {
285
+ const token = await createPaymentIntentToken({
286
+ paymentIntentCreateAttributes,
287
+ customerCreateAttributes,
288
+ });
289
+ const result = await confirmPayment(token);
290
+ if (result.status === "failed") {
291
+ setError("Payment failed. Please try again.");
292
+ }
293
+ return result;
294
+ } catch (error) {
295
+ setError(error instanceof Error ? error.message : "Unknown error");
296
+ return { status: "failed" };
293
297
  }
294
298
  }
295
299
 
@@ -301,8 +305,7 @@ function CheckoutWallets({ renderToken }: { renderToken: string }) {
301
305
  renderToken={renderToken}
302
306
  amount="50.00"
303
307
  merchantName="Example Store"
304
- onInitiatePaymentIntentRequest={createPaymentIntentToken}
305
- onResult={handleResult}
308
+ onConfirm={handleConfirm}
306
309
  />
307
310
  </div>
308
311
  <div style={{ flex: "1 1 0", minWidth: 0 }}>
@@ -310,8 +313,7 @@ function CheckoutWallets({ renderToken }: { renderToken: string }) {
310
313
  renderToken={renderToken}
311
314
  amount="50.00"
312
315
  merchantName="Example Store"
313
- onInitiatePaymentIntentRequest={createPaymentIntentToken}
314
- onResult={handleResult}
316
+ onConfirm={handleConfirm}
315
317
  />
316
318
  </div>
317
319
  </div>
@@ -321,7 +323,7 @@ function CheckoutWallets({ renderToken }: { renderToken: string }) {
321
323
  }
322
324
  ```
323
325
 
324
- Do not call `validateForm` or `confirmPaymentIntent` — return the embed token from `onInitiatePaymentIntentRequest` and the SDK confirms. Size the mount slot; omitted `buttonProps` keep paint defaults and fill the iframe.
326
+ Do not call `validateForm` from the host in an express flow — create a payment intent inside `onConfirm`, then `await confirmPayment(token)`. Size the mount slot; omitted `buttonProps` keep paint defaults and fill the iframe.
325
327
 
326
328
  On Safari, Apple Pay uses the native payment sheet. On other browsers, Apple's QR handoff opens in a popup (`pay.apple.com`); while that popup is open, the SDK shows a waiting overlay with **Cancel payment**.
327
329
 
@@ -335,8 +337,7 @@ Optional visuals:
335
337
  height="48px"
336
338
  buttonProps={{ buttonType: "donate", buttonBorderType: "no_border" }}
337
339
  iframeProps={{ style: { borderRadius: "8px" } }}
338
- onInitiatePaymentIntentRequest={createPaymentIntentToken}
339
- onResult={handleResult}
340
+ onConfirm={handleConfirm}
340
341
  />
341
342
 
342
343
  <AmosApplePayButton
@@ -346,8 +347,7 @@ Optional visuals:
346
347
  height="48px"
347
348
  buttonProps={{ type: "donate" }}
348
349
  iframeProps={{ style: { borderRadius: "8px" } }}
349
- onInitiatePaymentIntentRequest={createPaymentIntentToken}
350
- onResult={handleResult}
350
+ onConfirm={handleConfirm}
351
351
  />
352
352
  ```
353
353
 
@@ -357,7 +357,7 @@ Optional visuals:
357
357
  import { useRef, useState } from "react";
358
358
  import {
359
359
  AmosCreditCardPaymentMethodForm,
360
- confirmSetupIntent,
360
+ confirmSetup,
361
361
  validateForm,
362
362
  } from "@amos.com/react-amos-js";
363
363
 
@@ -393,7 +393,10 @@ function SavePaymentMethodForm() {
393
393
  }
394
394
 
395
395
  const { token } = await response.json();
396
- confirmSetupIntent({ iframeRef, token });
396
+ const result = await confirmSetup({ iframeRef, token });
397
+ if (result.status !== "succeeded") {
398
+ setError("Failed to save the payment method.");
399
+ }
397
400
  } catch (error) {
398
401
  setError(error instanceof Error ? error.message : "Unknown error");
399
402
  } finally {
@@ -406,15 +409,6 @@ function SavePaymentMethodForm() {
406
409
  <AmosCreditCardPaymentMethodForm
407
410
  ref={iframeRef}
408
411
  renderToken="the-render-token-that-you-created-on-dashboard.amos.com"
409
- onResult={(result) => {
410
- if (result.status === "succeeded") {
411
- console.log("Confirm returned:", result);
412
- } else if (result.status === "failed") {
413
- console.error("Confirm failed:", result.errorMessage);
414
- } else if (result.status === "incomplete") {
415
- console.log("Recoverable:", result.reason);
416
- }
417
- }}
418
412
  />
419
413
  {error ? <p>{error}</p> : null}
420
414
  <button type="submit" disabled={isProcessing}>
@@ -437,31 +431,31 @@ Validates the embedded card/bank iframe form before payment confirmation.
437
431
 
438
432
  **Returns:** `Promise<boolean>` (resolves to `false` after 5 seconds if the iframe does not respond).
439
433
 
440
- ### `confirmPaymentIntent({ iframeRef, token })`
434
+ ### `confirmPayment({ iframeRef, token })`
441
435
 
442
- Confirms a payment intent in the embedded iframe flow.
436
+ Confirms a payment intent in the embedded iframe flow. Resolves `{ status: "succeeded" }` or `{ status: "failed" }`. Deprecated alias: `confirmPaymentIntent`.
443
437
 
444
438
  **Parameters:**
445
439
 
446
440
  - `iframeRef` (`React.RefObject<HTMLIFrameElement | null> | undefined`, required)
447
441
  - `token` (typed as `Pick<components["schemas"]["EmbedToken"], "token">` — the embed JWT string returned by your server)
448
442
 
449
- **Returns:** `void`
443
+ **Returns:** `Promise<ConfirmResult>`
450
444
 
451
- ### `confirmSetupIntent({ iframeRef, token })`
445
+ ### `confirmSetup({ iframeRef, token })`
452
446
 
453
- Confirms a setup intent in the embedded iframe flow. Use this when saving a payment method for future use.
447
+ Confirms a setup intent in the embedded iframe flow. Use this when saving a payment method for future use. Deprecated alias: `confirmSetupIntent`.
454
448
 
455
449
  **Parameters:**
456
450
 
457
451
  - `iframeRef` (`React.RefObject<HTMLIFrameElement | null> | undefined`, required)
458
452
  - `token` (same `Pick<components["schemas"]["EmbedToken"], "token">` embed JWT string as for payment confirmation)
459
453
 
460
- **Returns:** `void`
454
+ **Returns:** `Promise<ConfirmResult>`
461
455
 
462
456
  ### `resetForm({ iframeRef })`
463
457
 
464
- Clears all field values and API errors in the embedded card/bank iframe form. Call after `onResult` when the customer wants to try again (for example, after a successful payment when starting a new one).
458
+ Clears all field values and API errors in the embedded card/bank iframe form. Call after a failed or incomplete confirm when the customer wants to try again (for example, after a successful payment when starting a new one).
465
459
 
466
460
  **Parameters:**
467
461
 
@@ -476,7 +470,6 @@ Renders the secure credit card iframe form. A field-shaped skeleton is shown imm
476
470
  **Required props:**
477
471
 
478
472
  - `renderToken` (`string`)
479
- - `onResult` (`(result: ConfirmationResult) => void`) — required. Called when the interactive confirmation attempt finishes (`succeeded`, `failed`, or `incomplete` with `reason`). Not settlement proof; verify via webhooks.
480
473
 
481
474
  **Optional props:**
482
475
 
@@ -484,6 +477,7 @@ Renders the secure credit card iframe form. A field-shaped skeleton is shown imm
484
477
 
485
478
  - `additionalFields` (`{ cardholderName: boolean }`) — set `additionalFields={{ cardholderName: true }}` to render the cardholder name field in the iframe (`false` by default)
486
479
  - `billingAddressRequirement` (`"country" | "full"`, defaults to `"country"`) — how much billing address the iframe collects. `country` collects country / region and, for CA / PR / GB / US, a postal code (labeled ZIP for the United States). `full` shows a full street address form with Smarty autocomplete.
480
+ - `onResult` (`(result: ConfirmationResult) => void`) — **deprecated.** Prefer `await confirmPayment()` / `await confirmSetup()`. Still fired for existing hosts (`succeeded`, `failed`, or `incomplete` with `reason`). Not settlement proof; verify via webhooks.
487
481
  - `onValidityChange` (`(event: { isValid: boolean }) => void`) — called when form validity changes. `isValid` is true when all required fields are present and valid. Does not include PCI data. Use this to enable or disable your checkout button.
488
482
  - `onCardBrandChanged` (`(event: { brand: CardBrand | null }) => void`) — called when the detected card brand changes. `brand` is `"visa"`, `"mastercard"`, `"amex"`, `"discover"`, `"diners"`, or `"jcb"`, or `null` when the field is empty or the number does not match a known brand. Does not include PCI data.
489
483
 
@@ -495,7 +489,7 @@ Renders the secure bank account iframe form. A field-shaped skeleton is shown im
495
489
 
496
490
  When the charge meets the merchant’s ACH verification threshold, the SDK hides the routing/account iframe and renders a **Connect bank account** button in the parent page. The button follows the same outline/focus defaults as Amos UI (`--ring`, `--border`, `--radius`, `--input-height`, …): it inherits those CSS variables from the host page when present, and `appearance.themeVariables` overrides them the same way as the iframe. Clicking it asks the iframe to mint a Plaid Link token, then opens [Plaid Link](https://plaid.com/docs/link/web/). Hosts do not proxy Pay API (`GET /merchants`, `POST /plaid_link_tokens`); embed does that with `PAY_API_KEY`. Do not put Plaid secrets in the browser.
497
491
 
498
- **Required props:** same as `AmosCreditCardPaymentMethodForm` — `renderToken`, `onResult` — plus:
492
+ **Required props:** same as `AmosCreditCardPaymentMethodForm` — `renderToken` — plus:
499
493
 
500
494
  - `amount` (`string`, major-currency decimal, e.g. `"50.00"`, defaults to `"0"`) — same format as Google Pay / Apple Pay. Compared to the threshold the iframe fetches (cents). Pass `"0"` (the default) on open-amount forms until the customer enters a charge — 0 is typically under the threshold, so Connect stays hidden. Pass a new `amount` when the customer changes the charge.
501
495
  - `intent` (`"payment" | "setup"`, defaults to `"payment"`) — `"setup"` always shows Connect / Plaid (no merchant ACH threshold lookup), unless the render token disables verification. Use this when saving a bank account for later charges.
@@ -508,7 +502,6 @@ Compare locally once the iframe posts `ACH_THRESHOLD`: Plaid when `requireVerifi
508
502
  <AmosBankAccountPaymentMethodForm
509
503
  renderToken={renderToken}
510
504
  amount="50.00" // defaults to "0" (manual form until the charge meets the threshold)
511
- onResult={onResult}
512
505
  />
513
506
  ```
514
507
 
@@ -518,11 +511,10 @@ Setup (always Connect, no merchant lookup):
518
511
  <AmosBankAccountPaymentMethodForm
519
512
  renderToken={renderToken}
520
513
  intent="setup"
521
- onResult={onResult}
522
514
  />
523
515
  ```
524
516
 
525
- `validateForm` / `confirmPaymentIntent` / `confirmSetupIntent` stay iframe-based. When Plaid succeeded, confirm sends `payment_method.plaid` (`public_token`, `account_id`) and does not require typed account numbers.
517
+ `validateForm` / `confirmPayment` / `confirmSetup` stay iframe-based. When Plaid succeeded, confirm sends `payment_method.plaid` (`public_token`, `account_id`) and does not require typed account numbers.
526
518
 
527
519
  **CSP:** the parent page must allow Plaid’s script and frames, for example `script-src https://cdn.plaid.com` and `frame-src https://cdn.plaid.com https://*.plaid.com`. Amos never loads `PLAID_SECRET` / `PLAID_CLIENT_ID` in the SDK or embed iframe.
528
520
 
@@ -537,9 +529,7 @@ Renders the secure Google Pay iframe button (express checkout flow). A button-sh
537
529
  - `renderToken` (`string`)
538
530
  - `amount` (`string`) — major-currency decimal string shown in the wallet sheet (e.g. `"50.00"` for $50.00). The iframe converts this to cents in `paymentIntentCreateAttributes.amount`.
539
531
  - `merchantName` (`string`)
540
- - `onInitiatePaymentIntentRequest` (callback receiving `{ paymentIntentCreateAttributes: components["schemas"]["CreatePaymentIntentInput"]; customerCreateAttributes: components["schemas"]["CreateCustomerInput"] }`, returns `Promise<components["schemas"]["EmbedToken"]["token"]>` — the embed JWT string for confirmation)
541
-
542
- - `onResult` (`(result: ConfirmationResult) => void`) — required. Called when the interactive confirmation attempt finishes (`succeeded`, `failed`, or `incomplete` with `reason`). Not settlement proof; verify via webhooks.
532
+ - `onConfirm` (callback receiving `{ paymentIntentCreateAttributes, customerCreateAttributes, confirmPayment }`. Create a payment intent, then `return confirmPayment(token)` — `Promise<ConfirmResult>`)
543
533
 
544
534
  **Optional props:**
545
535
 
@@ -595,14 +585,14 @@ Re-exports of the same advanced helpers exposed by `@amos.com/amos-js`. Most int
595
585
 
596
586
  ### Exported types
597
587
 
598
- `@amos.com/react-amos-js` re-exports everything from `@amos.com/amos-js`, including `ConfirmationResult`, `ConfirmationIncompleteReason`, `PaymentMethodFormValidityChangeEvent`, `CardBrand`, `PaymentMethodFormCardBrandChangeEvent`, `FormattedGooglePayPaymentData`, `Message`, `Appearance`, `ThemeVariable`, and the per-form `*Options` / `*Controller` types. For OpenAPI schema types (e.g. `PaymentIntent`, `CreatePaymentIntentInput`), import `components` from `@amos.com/node`.
588
+ `@amos.com/react-amos-js` re-exports everything from `@amos.com/amos-js`, including `ConfirmResult`, `ConfirmationResult` (deprecated), `ConfirmationIncompleteReason`, `PaymentMethodFormValidityChangeEvent`, `CardBrand`, `PaymentMethodFormCardBrandChangeEvent`, `FormattedGooglePayPaymentData`, `Message`, `Appearance`, `ThemeVariable`, and the per-form `*Options` / `*Controller` types. For OpenAPI schema types (e.g. `PaymentIntent`, `CreatePaymentIntentInput`), import `components` from `@amos.com/node`.
599
589
 
600
590
  ## Notes and potential gotchas
601
591
 
602
- - **`ref` / `iframeRef`**: for card and bank forms, pass `ref={iframeRef}` to the form component. The same `iframeRef` must be used when calling `validateForm`, `confirmPaymentIntent`, `confirmSetupIntent`, or `resetForm`. The component forwards the ref to the inner iframe.
603
- - **`onResult` is not settlement proof**: `onResult` tells you when to stop waiting (e.g. dismiss a spinner). Verify payment or setup success on your backend via webhooks. On `status: "incomplete"`, unlock your UI — the customer can fix fields in the iframe and retry. Use `result.reason` (`"field_errors"` or `"validation_failed"`) to distinguish recoverable states.
604
- - **Same components for payment vs setup intents**: `AmosCreditCardPaymentMethodForm` and `AmosBankAccountPaymentMethodForm` support both payment intents and setup intents. The flow differs only by which server call you make and which confirmation function you use (`confirmPaymentIntent` vs `confirmSetupIntent`). Handle both payment and setup outcomes via `onResult`.
605
- - **Amount format**: for `AmosGooglePayButton`, `AmosApplePayButton`, and `AmosBankAccountPaymentMethodForm`, `amount` is a major-currency decimal string (e.g. `"50.00"` for $50.00). For `components["schemas"]["CreatePaymentIntentInput"]` on the server (card/bank create, and the object the wallet iframe sends to `onInitiatePaymentIntentRequest`), `amount` is a number in cents (e.g. `5000`).
592
+ - **`ref` / `iframeRef`**: for card and bank forms, pass `ref={iframeRef}` to the form component. The same `iframeRef` must be used when calling `validateForm`, `confirmPayment`, `confirmSetup`, or `resetForm`. The component forwards the ref to the inner iframe.
593
+ - **`confirmPayment` / `confirmSetup` are not settlement proof**: `{ status: "succeeded" }` means authorization succeeded (capture may still finish asynchronously). Verify payment or setup success on your backend via webhooks. Recoverable field errors stay in the iframe; the Promise still resolves `{ status: "failed" }`. Deprecated `onResult` still receives `incomplete` with `reason` (`"field_errors"` or `"validation_failed"`).
594
+ - **Same components for payment vs setup intents**: `AmosCreditCardPaymentMethodForm` and `AmosBankAccountPaymentMethodForm` support both payment intents and setup intents. The flow differs only by which server call you make and which confirmation function you use (`confirmPayment` vs `confirmSetup`).
595
+ - **Amount format**: for `AmosGooglePayButton`, `AmosApplePayButton`, and `AmosBankAccountPaymentMethodForm`, `amount` is a major-currency decimal string (e.g. `"50.00"` for $50.00). For `components["schemas"]["CreatePaymentIntentInput"]` on the server (card/bank create, and the object the wallet iframe sends to `onConfirm`), `amount` is a number in cents (e.g. `5000`).
606
596
  - **Plaid Link (ACH verification)**: load `cdn.plaid.com` from the **parent** document (see CSP on `AmosBankAccountPaymentMethodForm`). Merchants do not proxy Pay API; the bank iframe fetches the ACH threshold for payment intents and mints link tokens. Setup intents skip the merchant lookup and always require Plaid unless the render token disables verification. Confirm still goes through the bank iframe so Amos can attach `plaid` to the payment method.
607
597
  - **Apple Pay waiting overlay**: on browsers where Apple's QR handoff opens in a popup (non-Safari), `AmosApplePayButton` shows a fixed full-viewport overlay on the host page until payment completes, the popup closes, or the user clicks **Cancel payment**. Avoid stacking other fixed UI above it.
608
598
  - **Going framework-free**: if you need to use Amos outside of React (vanilla JS, another framework, etc.), use [`@amos.com/amos-js`](../amos-js) directly.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /// <reference types="googlepay" />
2
- import { Appearance, ApplePayButtonElementProps, BillingAddressRequirement, ConfirmationResult, CreditCardAdditionalFields, GooglePayButtonElementProps } from '@amos.com/amos-js';
2
+ import { Appearance, ApplePayButtonElementProps, BillingAddressRequirement, ConfirmationResult, ConfirmResult, CreditCardAdditionalFields, GooglePayButtonElementProps } from '@amos.com/amos-js';
3
3
  import { components } from '@amos.com/node';
4
4
  import { ComponentProps, Ref, RefObject } from 'react';
5
5
  export * from '@amos.com/amos-js';
@@ -20,9 +20,9 @@ export declare function validateForm({ iframeRef, }: {
20
20
  * Pass the embed JWT (`token`) returned by your server's
21
21
  * `POST /payment_intents` call.
22
22
  */
23
- export declare function confirmPaymentIntent({ iframeRef, token, }: {
23
+ export declare function confirmPayment({ iframeRef, token, }: {
24
24
  iframeRef: IframeRef;
25
- } & Pick<components["schemas"]["EmbedToken"], "token">): void;
25
+ } & Pick<components["schemas"]["EmbedToken"], "token">): Promise<ConfirmResult>;
26
26
  /**
27
27
  * Confirm a setup intent in the embedded iframe flow. Use this when
28
28
  * saving a payment method for future use.
@@ -30,9 +30,21 @@ export declare function confirmPaymentIntent({ iframeRef, token, }: {
30
30
  * Pass the embed JWT (`token`) returned by your server's
31
31
  * `POST /setup_intents` call.
32
32
  */
33
+ export declare function confirmSetup({ iframeRef, token, }: {
34
+ iframeRef: IframeRef;
35
+ } & Pick<components["schemas"]["EmbedToken"], "token">): Promise<ConfirmResult>;
36
+ /**
37
+ * @deprecated Use {@link confirmPayment}.
38
+ */
39
+ export declare function confirmPaymentIntent({ iframeRef, token, }: {
40
+ iframeRef: IframeRef;
41
+ } & Pick<components["schemas"]["EmbedToken"], "token">): Promise<ConfirmResult>;
42
+ /**
43
+ * @deprecated Use {@link confirmSetup}.
44
+ */
33
45
  export declare function confirmSetupIntent({ iframeRef, token, }: {
34
46
  iframeRef: IframeRef;
35
- } & Pick<components["schemas"]["EmbedToken"], "token">): void;
47
+ } & Pick<components["schemas"]["EmbedToken"], "token">): Promise<ConfirmResult>;
36
48
  /**
37
49
  * Clear all field values and API errors in the embedded card/bank iframe
38
50
  * form. Call after `onResult` when the customer wants to try again.
@@ -45,7 +57,10 @@ type IframePassthroughProps = Omit<ComponentProps<"iframe">, "src" | "title" | "
45
57
  type AmosCreditCardPaymentMethodFormProps = IframePassthroughProps & {
46
58
  renderToken: string;
47
59
  appearance?: Appearance;
48
- onResult: (result: ConfirmationResult) => void;
60
+ /**
61
+ * @deprecated Prefer `await confirmPayment()` / `await confirmSetup()`.
62
+ */
63
+ onResult?: (result: ConfirmationResult) => void;
49
64
  /**
50
65
  * Called when form validity changes. `isValid` is true when all
51
66
  * required fields are present and valid. Does not include PCI data.
@@ -68,7 +83,10 @@ export declare function AmosCreditCardPaymentMethodForm({ ref, renderToken, appe
68
83
  type AmosBankAccountPaymentMethodFormProps = IframePassthroughProps & {
69
84
  renderToken: string;
70
85
  appearance?: Appearance;
71
- onResult: (result: ConfirmationResult) => void;
86
+ /**
87
+ * @deprecated Prefer `await confirmPayment()` / `await confirmSetup()`.
88
+ */
89
+ onResult?: (result: ConfirmationResult) => void;
72
90
  /**
73
91
  * Called when form validity changes. `isValid` is true when all
74
92
  * required fields are present and valid, or when Plaid Link has
@@ -126,18 +144,22 @@ type AmosGooglePayButtonProps = {
126
144
  buttonProps?: GooglePayButtonElementProps;
127
145
  /** Props applied to the host-page `<iframe>` element. */
128
146
  iframeProps?: IframePassthroughProps;
129
- onInitiatePaymentIntentRequest: ({ paymentIntentCreateAttributes, customerCreateAttributes, }: {
147
+ /**
148
+ * Called when the buyer authorizes in the Google Pay sheet. Create a
149
+ * payment intent on your server, then `await confirmPayment(token)`.
150
+ */
151
+ onConfirm: ({ paymentIntentCreateAttributes, customerCreateAttributes, confirmPayment, }: {
130
152
  paymentIntentCreateAttributes: components["schemas"]["CreatePaymentIntentInput"];
131
153
  customerCreateAttributes: components["schemas"]["CreateCustomerInput"];
132
- }) => Promise<components["schemas"]["EmbedToken"]["token"]>;
133
- onResult: (result: ConfirmationResult) => void;
154
+ confirmPayment: (token: string) => Promise<ConfirmResult>;
155
+ }) => Promise<ConfirmResult>;
134
156
  };
135
157
  /**
136
158
  * Renders the secure Google Pay iframe button. A button-shaped
137
159
  * skeleton is painted in the parent document on first render (including
138
160
  * SSR) so the slot height is reserved before the iframe loads.
139
161
  */
140
- export declare function AmosGooglePayButton({ ref, renderToken, amount, merchantName, height, buttonProps, iframeProps, onInitiatePaymentIntentRequest, onResult, }: AmosGooglePayButtonProps): import("react").JSX.Element;
162
+ export declare function AmosGooglePayButton({ ref, renderToken, amount, merchantName, height, buttonProps, iframeProps, onConfirm, }: AmosGooglePayButtonProps): import("react").JSX.Element;
141
163
  type AmosApplePayButtonProps = {
142
164
  ref?: ForwardedIframeRef;
143
165
  renderToken: string;
@@ -162,15 +184,19 @@ type AmosApplePayButtonProps = {
162
184
  buttonProps?: ApplePayButtonElementProps;
163
185
  /** Props applied to the host-page `<iframe>` element. */
164
186
  iframeProps?: IframePassthroughProps;
165
- onInitiatePaymentIntentRequest: ({ paymentIntentCreateAttributes, customerCreateAttributes, }: {
187
+ /**
188
+ * Called when the buyer authorizes in the Apple Pay sheet. Create a
189
+ * payment intent on your server, then `await confirmPayment(token)`.
190
+ */
191
+ onConfirm: ({ paymentIntentCreateAttributes, customerCreateAttributes, confirmPayment, }: {
166
192
  paymentIntentCreateAttributes: components["schemas"]["CreatePaymentIntentInput"];
167
193
  customerCreateAttributes: components["schemas"]["CreateCustomerInput"];
168
- }) => Promise<components["schemas"]["EmbedToken"]["token"]>;
169
- onResult: (result: ConfirmationResult) => void;
194
+ confirmPayment: (token: string) => Promise<ConfirmResult>;
195
+ }) => Promise<ConfirmResult>;
170
196
  };
171
197
  /**
172
198
  * Renders the secure Apple Pay iframe button. A button-shaped
173
199
  * skeleton is painted in the parent document on first render (including
174
200
  * SSR) so the slot height is reserved before the iframe loads.
175
201
  */
176
- export declare function AmosApplePayButton({ ref, renderToken, amount, merchantName, height, buttonProps, iframeProps, onInitiatePaymentIntentRequest, onResult, }: AmosApplePayButtonProps): import("react").JSX.Element;
202
+ export declare function AmosApplePayButton({ ref, renderToken, amount, merchantName, height, buttonProps, iframeProps, onConfirm, }: AmosApplePayButtonProps): import("react").JSX.Element;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@amos.com/amos-js"),t=require("react"),n=require("react/jsx-runtime");function r(e){return e?e.current??null:null}function i({iframeRef:t}){return(0,e.validateForm)({iframe:r(t)})}function a({iframeRef:t,token:n}){(0,e.confirmPaymentIntent)({iframe:r(t),token:n})}function o({iframeRef:t,token:n}){(0,e.confirmSetupIntent)({iframe:r(t),token:n})}function s({iframeRef:t}){(0,e.resetForm)({iframe:r(t)})}function c(e,t){typeof e==`function`?e(t):e&&(e.current=t)}function l(e,{style:t,className:n,id:r,...i}){n!=null&&(e.className=n),r!=null&&(e.id=r),Object.assign(e.style,t);for(let[t,n]of Object.entries(i))n!=null&&(t in e?Reflect.set(e,t,n):e.setAttribute(t,String(n)))}function u({containerRef:e,iframeRef:n,mount:r,options:i,remountDeps:a,iframePassthrough:o,updateDeps:s}){let u=(0,t.useRef)(null);(0,t.useLayoutEffect)(()=>{let t=e.current;if(!t)return;let a=r(t,i);return u.current=a,c(n,a.iframe),l(a.iframe,o),()=>{a.destroy(),u.current=null,c(n,null)}},[...a]),(0,t.useEffect)(()=>{u.current?.update(i)},[...s]),(0,t.useEffect)(()=>{let e=u.current?.iframe;e&&l(e,o)})}var d=`oklch(0.97 0 0)`;function f({height:r,borderRadius:i,containerRef:a}){return(0,t.useLayoutEffect)(()=>{(0,e.ensureSkeletonStyles)()},[]),(0,n.jsxs)(`div`,{style:{boxSizing:`border-box`,position:`relative`,width:`100%`,height:r,minHeight:r,overflow:`hidden`},children:[(0,n.jsx)(`div`,{className:`amos-js-form-skeleton-input amos-js-wallet-skeleton`,style:{position:`absolute`,inset:0,height:r,borderRadius:i,background:d,pointerEvents:`none`,zIndex:0},"aria-hidden":!0}),(0,n.jsx)(`div`,{ref:a,style:{position:`absolute`,inset:0,zIndex:1,width:`100%`,height:`100%`}})]})}function p({ref:r,renderToken:i,appearance:a,onResult:o,onValidityChange:s,onCardBrandChanged:c,additionalFields:l={cardholderName:!1},billingAddressRequirement:d=`country`,style:f,...p}){let m=(0,t.useRef)(null);return u({containerRef:m,iframeRef:r,mount:e.mountAmosCreditCardPaymentMethodForm,options:{renderToken:i,appearance:a,additionalFields:l,billingAddressRequirement:d,onResult:o,onValidityChange:s,onCardBrandChanged:c},remountDeps:[i,l.cardholderName,d],iframePassthrough:{style:f,...p},updateDeps:[a,l,d,o,s,c]}),(0,n.jsx)(`div`,{ref:m})}function m({ref:r,renderToken:i,appearance:a,onResult:o,onValidityChange:s,billingAddressRequirement:c=`country`,amount:l=`0`,intent:d=`payment`,style:f,...p}){let m=(0,t.useRef)(null);return u({containerRef:m,iframeRef:r,mount:e.mountAmosBankAccountPaymentMethodForm,options:{renderToken:i,appearance:a,billingAddressRequirement:c,amount:l,intent:d,onResult:o,onValidityChange:s},remountDeps:[i,c,d],iframePassthrough:{style:f,...p},updateDeps:[a,c,l,d,o,s]}),(0,n.jsx)(`div`,{ref:m})}function h({ref:r,renderToken:i,amount:a,merchantName:o,height:s=`48px`,buttonProps:c,iframeProps:l,onInitiatePaymentIntentRequest:d,onResult:p}){let m=(0,t.useRef)(null),h=(0,e.resolveWalletButtonSkeletonBorderRadius)({iframeStyle:l?.style,buttonProps:c});return u({containerRef:m,iframeRef:r,mount:e.mountAmosGooglePayButton,options:{renderToken:i,amount:a,merchantName:o,height:s,buttonProps:c,onInitiatePaymentIntentRequest:d,onResult:p},remountDeps:[i],iframePassthrough:l??{},updateDeps:[a,o,s,c,d,p]}),(0,n.jsx)(f,{height:s,borderRadius:h,containerRef:m})}function g({ref:r,renderToken:i,amount:a,merchantName:o,height:s=`48px`,buttonProps:c,iframeProps:l,onInitiatePaymentIntentRequest:d,onResult:p}){let m=(0,t.useRef)(null),h=(0,e.resolveWalletButtonSkeletonBorderRadius)({iframeStyle:l?.style,buttonProps:c});return u({containerRef:m,iframeRef:r,mount:e.mountAmosApplePayButton,options:{renderToken:i,amount:a,merchantName:o,height:s,buttonProps:c,onInitiatePaymentIntentRequest:d,onResult:p},remountDeps:[i],iframePassthrough:l??{},updateDeps:[a,o,s,c,d,p]}),(0,n.jsx)(f,{height:s,borderRadius:h,containerRef:m})}exports.AmosApplePayButton=g,exports.AmosBankAccountPaymentMethodForm=m,exports.AmosCreditCardPaymentMethodForm=p,exports.AmosGooglePayButton=h,exports.confirmPaymentIntent=a,exports.confirmSetupIntent=o,exports.resetForm=s,exports.validateForm=i,Object.keys(e).forEach(function(t){t!=="default"&&!Object.prototype.hasOwnProperty.call(exports,t)&&Object.defineProperty(exports,t,{enumerable:!0,get:function(){return e[t]}})});
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@amos.com/amos-js"),t=require("react"),n=require("react/jsx-runtime");function r(e){return e?e.current??null:null}function i({iframeRef:t}){return(0,e.validateForm)({iframe:r(t)})}function a({iframeRef:t,token:n}){return(0,e.confirmPayment)({iframe:r(t),token:n})}function o({iframeRef:t,token:n}){return(0,e.confirmSetup)({iframe:r(t),token:n})}function s({iframeRef:t,token:n}){return(0,e.confirmPaymentIntent)({iframe:r(t),token:n})}function c({iframeRef:t,token:n}){return(0,e.confirmSetupIntent)({iframe:r(t),token:n})}function l({iframeRef:t}){(0,e.resetForm)({iframe:r(t)})}function u(e,t){typeof e==`function`?e(t):e&&(e.current=t)}function d(e,{style:t,className:n,id:r,...i}){n!=null&&(e.className=n),r!=null&&(e.id=r),Object.assign(e.style,t);for(let[t,n]of Object.entries(i))n!=null&&(t in e?Reflect.set(e,t,n):e.setAttribute(t,String(n)))}function f({containerRef:e,iframeRef:n,mount:r,options:i,remountDeps:a,iframePassthrough:o,updateDeps:s}){let c=(0,t.useRef)(null);(0,t.useLayoutEffect)(()=>{let t=e.current;if(!t)return;let a=r(t,i);return c.current=a,u(n,a.iframe),d(a.iframe,o),()=>{a.destroy(),c.current=null,u(n,null)}},[...a]),(0,t.useEffect)(()=>{c.current?.update(i)},[...s]),(0,t.useEffect)(()=>{let e=c.current?.iframe;e&&d(e,o)})}var p=`oklch(0.97 0 0)`;function m({height:r,borderRadius:i,containerRef:a}){return(0,t.useLayoutEffect)(()=>{(0,e.ensureSkeletonStyles)()},[]),(0,n.jsxs)(`div`,{style:{boxSizing:`border-box`,position:`relative`,width:`100%`,height:r,minHeight:r,overflow:`hidden`},children:[(0,n.jsx)(`div`,{className:`amos-js-form-skeleton-input amos-js-wallet-skeleton`,style:{position:`absolute`,inset:0,height:r,borderRadius:i,background:p,pointerEvents:`none`,zIndex:0},"aria-hidden":!0}),(0,n.jsx)(`div`,{ref:a,style:{position:`absolute`,inset:0,zIndex:1,width:`100%`,height:`100%`}})]})}function h({ref:r,renderToken:i,appearance:a,onResult:o,onValidityChange:s,onCardBrandChanged:c,additionalFields:l={cardholderName:!1},billingAddressRequirement:u=`country`,style:d,...p}){let m=(0,t.useRef)(null);return f({containerRef:m,iframeRef:r,mount:e.mountAmosCreditCardPaymentMethodForm,options:{renderToken:i,appearance:a,additionalFields:l,billingAddressRequirement:u,onResult:o,onValidityChange:s,onCardBrandChanged:c},remountDeps:[i,l.cardholderName,u],iframePassthrough:{style:d,...p},updateDeps:[a,l,u,o,s,c]}),(0,n.jsx)(`div`,{ref:m})}function g({ref:r,renderToken:i,appearance:a,onResult:o,onValidityChange:s,billingAddressRequirement:c=`country`,amount:l=`0`,intent:u=`payment`,style:d,...p}){let m=(0,t.useRef)(null);return f({containerRef:m,iframeRef:r,mount:e.mountAmosBankAccountPaymentMethodForm,options:{renderToken:i,appearance:a,billingAddressRequirement:c,amount:l,intent:u,onResult:o,onValidityChange:s},remountDeps:[i,c,u],iframePassthrough:{style:d,...p},updateDeps:[a,c,l,u,o,s]}),(0,n.jsx)(`div`,{ref:m})}function _({ref:r,renderToken:i,amount:a,merchantName:o,height:s=`48px`,buttonProps:c,iframeProps:l,onConfirm:u}){let d=(0,t.useRef)(null),p=(0,e.resolveWalletButtonSkeletonBorderRadius)({iframeStyle:l?.style,buttonProps:c});return f({containerRef:d,iframeRef:r,mount:e.mountAmosGooglePayButton,options:{renderToken:i,amount:a,merchantName:o,height:s,buttonProps:c,onConfirm:u},remountDeps:[i],iframePassthrough:l??{},updateDeps:[a,o,s,c,u]}),(0,n.jsx)(m,{height:s,borderRadius:p,containerRef:d})}function v({ref:r,renderToken:i,amount:a,merchantName:o,height:s=`48px`,buttonProps:c,iframeProps:l,onConfirm:u}){let d=(0,t.useRef)(null),p=(0,e.resolveWalletButtonSkeletonBorderRadius)({iframeStyle:l?.style,buttonProps:c});return f({containerRef:d,iframeRef:r,mount:e.mountAmosApplePayButton,options:{renderToken:i,amount:a,merchantName:o,height:s,buttonProps:c,onConfirm:u},remountDeps:[i],iframePassthrough:l??{},updateDeps:[a,o,s,c,u]}),(0,n.jsx)(m,{height:s,borderRadius:p,containerRef:d})}exports.AmosApplePayButton=v,exports.AmosBankAccountPaymentMethodForm=g,exports.AmosCreditCardPaymentMethodForm=h,exports.AmosGooglePayButton=_,exports.confirmPayment=a,exports.confirmPaymentIntent=s,exports.confirmSetup=o,exports.confirmSetupIntent=c,exports.resetForm=l,exports.validateForm=i,Object.keys(e).forEach(function(t){t!=="default"&&!Object.prototype.hasOwnProperty.call(exports,t)&&Object.defineProperty(exports,t,{enumerable:!0,get:function(){return e[t]}})});
package/dist/index.mjs CHANGED
@@ -1,57 +1,69 @@
1
- import { confirmPaymentIntent as e, confirmSetupIntent as t, ensureSkeletonStyles as n, mountAmosApplePayButton as r, mountAmosBankAccountPaymentMethodForm as i, mountAmosCreditCardPaymentMethodForm as a, mountAmosGooglePayButton as o, resetForm as s, resolveWalletButtonSkeletonBorderRadius as c, validateForm as l } from "@amos.com/amos-js";
2
- import { useEffect as u, useLayoutEffect as d, useRef as f } from "react";
3
- import { jsx as p, jsxs as m } from "react/jsx-runtime";
1
+ import { confirmPayment as e, confirmPaymentIntent as t, confirmSetup as n, confirmSetupIntent as r, ensureSkeletonStyles as i, mountAmosApplePayButton as a, mountAmosBankAccountPaymentMethodForm as o, mountAmosCreditCardPaymentMethodForm as s, mountAmosGooglePayButton as c, resetForm as l, resolveWalletButtonSkeletonBorderRadius as u, validateForm as d } from "@amos.com/amos-js";
2
+ import { useEffect as f, useLayoutEffect as p, useRef as m } from "react";
3
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
4
4
  export * from "@amos.com/amos-js";
5
5
  //#region src/index.tsx
6
- function h(e) {
6
+ function _(e) {
7
7
  return e ? e.current ?? null : null;
8
8
  }
9
- function g({ iframeRef: e }) {
10
- return l({ iframe: h(e) });
9
+ function v({ iframeRef: e }) {
10
+ return d({ iframe: _(e) });
11
11
  }
12
- function _({ iframeRef: t, token: n }) {
13
- e({
14
- iframe: h(t),
12
+ function y({ iframeRef: t, token: n }) {
13
+ return e({
14
+ iframe: _(t),
15
15
  token: n
16
16
  });
17
17
  }
18
- function v({ iframeRef: e, token: n }) {
19
- t({
20
- iframe: h(e),
18
+ function b({ iframeRef: e, token: t }) {
19
+ return n({
20
+ iframe: _(e),
21
+ token: t
22
+ });
23
+ }
24
+ function x({ iframeRef: e, token: n }) {
25
+ return t({
26
+ iframe: _(e),
21
27
  token: n
22
28
  });
23
29
  }
24
- function y({ iframeRef: e }) {
25
- s({ iframe: h(e) });
30
+ function S({ iframeRef: e, token: t }) {
31
+ return r({
32
+ iframe: _(e),
33
+ token: t
34
+ });
35
+ }
36
+ function C({ iframeRef: e }) {
37
+ l({ iframe: _(e) });
26
38
  }
27
- function b(e, t) {
39
+ function w(e, t) {
28
40
  typeof e == "function" ? e(t) : e && (e.current = t);
29
41
  }
30
- function x(e, { style: t, className: n, id: r, ...i }) {
42
+ function T(e, { style: t, className: n, id: r, ...i }) {
31
43
  n != null && (e.className = n), r != null && (e.id = r), Object.assign(e.style, t);
32
44
  for (let [t, n] of Object.entries(i)) n != null && (t in e ? Reflect.set(e, t, n) : e.setAttribute(t, String(n)));
33
45
  }
34
- function S({ containerRef: e, iframeRef: t, mount: n, options: r, remountDeps: i, iframePassthrough: a, updateDeps: o }) {
35
- let s = f(null);
36
- d(() => {
46
+ function E({ containerRef: e, iframeRef: t, mount: n, options: r, remountDeps: i, iframePassthrough: a, updateDeps: o }) {
47
+ let s = m(null);
48
+ p(() => {
37
49
  let i = e.current;
38
50
  if (!i) return;
39
51
  let o = n(i, r);
40
- return s.current = o, b(t, o.iframe), x(o.iframe, a), () => {
41
- o.destroy(), s.current = null, b(t, null);
52
+ return s.current = o, w(t, o.iframe), T(o.iframe, a), () => {
53
+ o.destroy(), s.current = null, w(t, null);
42
54
  };
43
- }, [...i]), u(() => {
55
+ }, [...i]), f(() => {
44
56
  s.current?.update(r);
45
- }, [...o]), u(() => {
57
+ }, [...o]), f(() => {
46
58
  let e = s.current?.iframe;
47
- e && x(e, a);
59
+ e && T(e, a);
48
60
  });
49
61
  }
50
- var C = "oklch(0.97 0 0)";
51
- function w({ height: e, borderRadius: t, containerRef: r }) {
52
- return d(() => {
53
- n();
54
- }, []), /* @__PURE__ */ m("div", {
62
+ var D = "oklch(0.97 0 0)";
63
+ function O({ height: e, borderRadius: t, containerRef: n }) {
64
+ return p(() => {
65
+ i();
66
+ }, []), /* @__PURE__ */ g("div", {
55
67
  style: {
56
68
  boxSizing: "border-box",
57
69
  position: "relative",
@@ -60,20 +72,20 @@ function w({ height: e, borderRadius: t, containerRef: r }) {
60
72
  minHeight: e,
61
73
  overflow: "hidden"
62
74
  },
63
- children: [/* @__PURE__ */ p("div", {
75
+ children: [/* @__PURE__ */ h("div", {
64
76
  className: "amos-js-form-skeleton-input amos-js-wallet-skeleton",
65
77
  style: {
66
78
  position: "absolute",
67
79
  inset: 0,
68
80
  height: e,
69
81
  borderRadius: t,
70
- background: C,
82
+ background: D,
71
83
  pointerEvents: "none",
72
84
  zIndex: 0
73
85
  },
74
86
  "aria-hidden": !0
75
- }), /* @__PURE__ */ p("div", {
76
- ref: r,
87
+ }), /* @__PURE__ */ h("div", {
88
+ ref: n,
77
89
  style: {
78
90
  position: "absolute",
79
91
  inset: 0,
@@ -84,24 +96,24 @@ function w({ height: e, borderRadius: t, containerRef: r }) {
84
96
  })]
85
97
  });
86
98
  }
87
- function T({ ref: e, renderToken: t, appearance: n, onResult: r, onValidityChange: i, onCardBrandChanged: o, additionalFields: s = { cardholderName: !1 }, billingAddressRequirement: c = "country", style: l, ...u }) {
88
- let d = f(null);
89
- return S({
99
+ function k({ ref: e, renderToken: t, appearance: n, onResult: r, onValidityChange: i, onCardBrandChanged: a, additionalFields: o = { cardholderName: !1 }, billingAddressRequirement: c = "country", style: l, ...u }) {
100
+ let d = m(null);
101
+ return E({
90
102
  containerRef: d,
91
103
  iframeRef: e,
92
- mount: a,
104
+ mount: s,
93
105
  options: {
94
106
  renderToken: t,
95
107
  appearance: n,
96
- additionalFields: s,
108
+ additionalFields: o,
97
109
  billingAddressRequirement: c,
98
110
  onResult: r,
99
111
  onValidityChange: i,
100
- onCardBrandChanged: o
112
+ onCardBrandChanged: a
101
113
  },
102
114
  remountDeps: [
103
115
  t,
104
- s.cardholderName,
116
+ o.cardholderName,
105
117
  c
106
118
  ],
107
119
  iframePassthrough: {
@@ -110,32 +122,32 @@ function T({ ref: e, renderToken: t, appearance: n, onResult: r, onValidityChang
110
122
  },
111
123
  updateDeps: [
112
124
  n,
113
- s,
125
+ o,
114
126
  c,
115
127
  r,
116
128
  i,
117
- o
129
+ a
118
130
  ]
119
- }), /* @__PURE__ */ p("div", { ref: d });
131
+ }), /* @__PURE__ */ h("div", { ref: d });
120
132
  }
121
- function E({ ref: e, renderToken: t, appearance: n, onResult: r, onValidityChange: a, billingAddressRequirement: o = "country", amount: s = "0", intent: c = "payment", style: l, ...u }) {
122
- let d = f(null);
123
- return S({
133
+ function A({ ref: e, renderToken: t, appearance: n, onResult: r, onValidityChange: i, billingAddressRequirement: a = "country", amount: s = "0", intent: c = "payment", style: l, ...u }) {
134
+ let d = m(null);
135
+ return E({
124
136
  containerRef: d,
125
137
  iframeRef: e,
126
- mount: i,
138
+ mount: o,
127
139
  options: {
128
140
  renderToken: t,
129
141
  appearance: n,
130
- billingAddressRequirement: o,
142
+ billingAddressRequirement: a,
131
143
  amount: s,
132
144
  intent: c,
133
145
  onResult: r,
134
- onValidityChange: a
146
+ onValidityChange: i
135
147
  },
136
148
  remountDeps: [
137
149
  t,
138
- o,
150
+ a,
139
151
  c
140
152
  ],
141
153
  iframePassthrough: {
@@ -144,81 +156,77 @@ function E({ ref: e, renderToken: t, appearance: n, onResult: r, onValidityChang
144
156
  },
145
157
  updateDeps: [
146
158
  n,
147
- o,
159
+ a,
148
160
  s,
149
161
  c,
150
162
  r,
151
- a
163
+ i
152
164
  ]
153
- }), /* @__PURE__ */ p("div", { ref: d });
165
+ }), /* @__PURE__ */ h("div", { ref: d });
154
166
  }
155
- function D({ ref: e, renderToken: t, amount: n, merchantName: r, height: i = "48px", buttonProps: a, iframeProps: s, onInitiatePaymentIntentRequest: l, onResult: u }) {
156
- let d = f(null), m = c({
157
- iframeStyle: s?.style,
167
+ function j({ ref: e, renderToken: t, amount: n, merchantName: r, height: i = "48px", buttonProps: a, iframeProps: o, onConfirm: s }) {
168
+ let l = m(null), d = u({
169
+ iframeStyle: o?.style,
158
170
  buttonProps: a
159
171
  });
160
- return S({
161
- containerRef: d,
172
+ return E({
173
+ containerRef: l,
162
174
  iframeRef: e,
163
- mount: o,
175
+ mount: c,
164
176
  options: {
165
177
  renderToken: t,
166
178
  amount: n,
167
179
  merchantName: r,
168
180
  height: i,
169
181
  buttonProps: a,
170
- onInitiatePaymentIntentRequest: l,
171
- onResult: u
182
+ onConfirm: s
172
183
  },
173
184
  remountDeps: [t],
174
- iframePassthrough: s ?? {},
185
+ iframePassthrough: o ?? {},
175
186
  updateDeps: [
176
187
  n,
177
188
  r,
178
189
  i,
179
190
  a,
180
- l,
181
- u
191
+ s
182
192
  ]
183
- }), /* @__PURE__ */ p(w, {
193
+ }), /* @__PURE__ */ h(O, {
184
194
  height: i,
185
- borderRadius: m,
186
- containerRef: d
195
+ borderRadius: d,
196
+ containerRef: l
187
197
  });
188
198
  }
189
- function O({ ref: e, renderToken: t, amount: n, merchantName: i, height: a = "48px", buttonProps: o, iframeProps: s, onInitiatePaymentIntentRequest: l, onResult: u }) {
190
- let d = f(null), m = c({
199
+ function M({ ref: e, renderToken: t, amount: n, merchantName: r, height: i = "48px", buttonProps: o, iframeProps: s, onConfirm: c }) {
200
+ let l = m(null), d = u({
191
201
  iframeStyle: s?.style,
192
202
  buttonProps: o
193
203
  });
194
- return S({
195
- containerRef: d,
204
+ return E({
205
+ containerRef: l,
196
206
  iframeRef: e,
197
- mount: r,
207
+ mount: a,
198
208
  options: {
199
209
  renderToken: t,
200
210
  amount: n,
201
- merchantName: i,
202
- height: a,
211
+ merchantName: r,
212
+ height: i,
203
213
  buttonProps: o,
204
- onInitiatePaymentIntentRequest: l,
205
- onResult: u
214
+ onConfirm: c
206
215
  },
207
216
  remountDeps: [t],
208
217
  iframePassthrough: s ?? {},
209
218
  updateDeps: [
210
219
  n,
220
+ r,
211
221
  i,
212
- a,
213
222
  o,
214
- l,
215
- u
223
+ c
216
224
  ]
217
- }), /* @__PURE__ */ p(w, {
218
- height: a,
219
- borderRadius: m,
220
- containerRef: d
225
+ }), /* @__PURE__ */ h(O, {
226
+ height: i,
227
+ borderRadius: d,
228
+ containerRef: l
221
229
  });
222
230
  }
223
231
  //#endregion
224
- export { O as AmosApplePayButton, E as AmosBankAccountPaymentMethodForm, T as AmosCreditCardPaymentMethodForm, D as AmosGooglePayButton, _ as confirmPaymentIntent, v as confirmSetupIntent, y as resetForm, g as validateForm };
232
+ export { M as AmosApplePayButton, A as AmosBankAccountPaymentMethodForm, k as AmosCreditCardPaymentMethodForm, j as AmosGooglePayButton, y as confirmPayment, x as confirmPaymentIntent, b as confirmSetup, S as confirmSetupIntent, C as resetForm, v as validateForm };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amos.com/react-amos-js",
3
- "version": "0.10.5",
3
+ "version": "0.11.1",
4
4
  "main": "dist/index.js",
5
5
  "repository": {
6
6
  "type": "git",
@@ -37,22 +37,22 @@
37
37
  "license": "MIT",
38
38
  "description": "React SDK for embedding Amos payment methods via iframes. Wraps @amos.com/amos-js.",
39
39
  "devDependencies": {
40
- "@amos.com/node": "0.1.50",
41
- "@biomejs/biome": "2.5.7",
40
+ "@amos.com/node": "0.1.53",
41
+ "@biomejs/biome": "2.5.10",
42
42
  "@changesets/cli": "2.31.1",
43
- "@types/node": "26.1.2",
43
+ "@types/node": "26.3.0",
44
44
  "@types/react": "19.2.18",
45
45
  "@typescript/typescript6": "6.0.2",
46
46
  "typescript": "7.0.2",
47
- "vite": "8.2.0",
47
+ "vite": "8.2.2",
48
48
  "vite-plugin-dts": "5.0.3"
49
49
  },
50
50
  "dependencies": {
51
- "@amos.com/amos-js": "0.10.5",
52
- "@types/googlepay": "0.7.11"
51
+ "@amos.com/amos-js": "0.11.2",
52
+ "@types/googlepay": "0.7.12"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "react": "^17 || ^18 || ^19",
56
- "@amos.com/node": ">=0.1.50"
56
+ "@amos.com/node": ">=0.1.53"
57
57
  }
58
58
  }
package/src/index.tsx CHANGED
@@ -3,12 +3,15 @@
3
3
  import {
4
4
  type Appearance,
5
5
  type ApplePayButtonElementProps,
6
+ confirmPayment as amosConfirmPayment,
6
7
  confirmPaymentIntent as amosConfirmPaymentIntent,
8
+ confirmSetup as amosConfirmSetup,
7
9
  confirmSetupIntent as amosConfirmSetupIntent,
8
10
  resetForm as amosResetForm,
9
11
  validateForm as amosValidateForm,
10
12
  type BillingAddressRequirement,
11
13
  type ConfirmationResult,
14
+ type ConfirmResult,
12
15
  type CreditCardAdditionalFields,
13
16
  ensureSkeletonStyles,
14
17
  type GooglePayButtonElementProps,
@@ -60,13 +63,16 @@ export function validateForm({
60
63
  * Pass the embed JWT (`token`) returned by your server's
61
64
  * `POST /payment_intents` call.
62
65
  */
63
- export function confirmPaymentIntent({
66
+ export function confirmPayment({
64
67
  iframeRef,
65
68
  token,
66
69
  }: {
67
70
  iframeRef: IframeRef;
68
- } & Pick<components["schemas"]["EmbedToken"], "token">): void {
69
- amosConfirmPaymentIntent({ iframe: resolveIframe(iframeRef), token });
71
+ } & Pick<
72
+ components["schemas"]["EmbedToken"],
73
+ "token"
74
+ >): Promise<ConfirmResult> {
75
+ return amosConfirmPayment({ iframe: resolveIframe(iframeRef), token });
70
76
  }
71
77
 
72
78
  /**
@@ -76,13 +82,46 @@ export function confirmPaymentIntent({
76
82
  * Pass the embed JWT (`token`) returned by your server's
77
83
  * `POST /setup_intents` call.
78
84
  */
85
+ export function confirmSetup({
86
+ iframeRef,
87
+ token,
88
+ }: {
89
+ iframeRef: IframeRef;
90
+ } & Pick<
91
+ components["schemas"]["EmbedToken"],
92
+ "token"
93
+ >): Promise<ConfirmResult> {
94
+ return amosConfirmSetup({ iframe: resolveIframe(iframeRef), token });
95
+ }
96
+
97
+ /**
98
+ * @deprecated Use {@link confirmPayment}.
99
+ */
100
+ export function confirmPaymentIntent({
101
+ iframeRef,
102
+ token,
103
+ }: {
104
+ iframeRef: IframeRef;
105
+ } & Pick<
106
+ components["schemas"]["EmbedToken"],
107
+ "token"
108
+ >): Promise<ConfirmResult> {
109
+ return amosConfirmPaymentIntent({ iframe: resolveIframe(iframeRef), token });
110
+ }
111
+
112
+ /**
113
+ * @deprecated Use {@link confirmSetup}.
114
+ */
79
115
  export function confirmSetupIntent({
80
116
  iframeRef,
81
117
  token,
82
118
  }: {
83
119
  iframeRef: IframeRef;
84
- } & Pick<components["schemas"]["EmbedToken"], "token">): void {
85
- amosConfirmSetupIntent({ iframe: resolveIframe(iframeRef), token });
120
+ } & Pick<
121
+ components["schemas"]["EmbedToken"],
122
+ "token"
123
+ >): Promise<ConfirmResult> {
124
+ return amosConfirmSetupIntent({ iframe: resolveIframe(iframeRef), token });
86
125
  }
87
126
 
88
127
  /**
@@ -247,7 +286,10 @@ function WalletButtonSlot({
247
286
  type AmosCreditCardPaymentMethodFormProps = IframePassthroughProps & {
248
287
  renderToken: string;
249
288
  appearance?: Appearance;
250
- onResult: (result: ConfirmationResult) => void;
289
+ /**
290
+ * @deprecated Prefer `await confirmPayment()` / `await confirmSetup()`.
291
+ */
292
+ onResult?: (result: ConfirmationResult) => void;
251
293
  /**
252
294
  * Called when form validity changes. `isValid` is true when all
253
295
  * required fields are present and valid. Does not include PCI data.
@@ -321,7 +363,10 @@ export function AmosCreditCardPaymentMethodForm({
321
363
  type AmosBankAccountPaymentMethodFormProps = IframePassthroughProps & {
322
364
  renderToken: string;
323
365
  appearance?: Appearance;
324
- onResult: (result: ConfirmationResult) => void;
366
+ /**
367
+ * @deprecated Prefer `await confirmPayment()` / `await confirmSetup()`.
368
+ */
369
+ onResult?: (result: ConfirmationResult) => void;
325
370
  /**
326
371
  * Called when form validity changes. `isValid` is true when all
327
372
  * required fields are present and valid, or when Plaid Link has
@@ -419,14 +464,19 @@ type AmosGooglePayButtonProps = {
419
464
  buttonProps?: GooglePayButtonElementProps;
420
465
  /** Props applied to the host-page `<iframe>` element. */
421
466
  iframeProps?: IframePassthroughProps;
422
- onInitiatePaymentIntentRequest: ({
467
+ /**
468
+ * Called when the buyer authorizes in the Google Pay sheet. Create a
469
+ * payment intent on your server, then `await confirmPayment(token)`.
470
+ */
471
+ onConfirm: ({
423
472
  paymentIntentCreateAttributes,
424
473
  customerCreateAttributes,
474
+ confirmPayment,
425
475
  }: {
426
476
  paymentIntentCreateAttributes: components["schemas"]["CreatePaymentIntentInput"];
427
477
  customerCreateAttributes: components["schemas"]["CreateCustomerInput"];
428
- }) => Promise<components["schemas"]["EmbedToken"]["token"]>;
429
- onResult: (result: ConfirmationResult) => void;
478
+ confirmPayment: (token: string) => Promise<ConfirmResult>;
479
+ }) => Promise<ConfirmResult>;
430
480
  };
431
481
 
432
482
  /**
@@ -442,8 +492,7 @@ export function AmosGooglePayButton({
442
492
  height = "48px",
443
493
  buttonProps,
444
494
  iframeProps,
445
- onInitiatePaymentIntentRequest,
446
- onResult,
495
+ onConfirm,
447
496
  }: AmosGooglePayButtonProps) {
448
497
  const containerRef = useRef<HTMLDivElement | null>(null);
449
498
  const borderRadius = resolveWalletButtonSkeletonBorderRadius({
@@ -461,19 +510,11 @@ export function AmosGooglePayButton({
461
510
  merchantName,
462
511
  height,
463
512
  buttonProps,
464
- onInitiatePaymentIntentRequest,
465
- onResult,
513
+ onConfirm,
466
514
  },
467
515
  remountDeps: [renderToken],
468
516
  iframePassthrough: iframeProps ?? {},
469
- updateDeps: [
470
- amount,
471
- merchantName,
472
- height,
473
- buttonProps,
474
- onInitiatePaymentIntentRequest,
475
- onResult,
476
- ],
517
+ updateDeps: [amount, merchantName, height, buttonProps, onConfirm],
477
518
  });
478
519
 
479
520
  return (
@@ -509,14 +550,19 @@ type AmosApplePayButtonProps = {
509
550
  buttonProps?: ApplePayButtonElementProps;
510
551
  /** Props applied to the host-page `<iframe>` element. */
511
552
  iframeProps?: IframePassthroughProps;
512
- onInitiatePaymentIntentRequest: ({
553
+ /**
554
+ * Called when the buyer authorizes in the Apple Pay sheet. Create a
555
+ * payment intent on your server, then `await confirmPayment(token)`.
556
+ */
557
+ onConfirm: ({
513
558
  paymentIntentCreateAttributes,
514
559
  customerCreateAttributes,
560
+ confirmPayment,
515
561
  }: {
516
562
  paymentIntentCreateAttributes: components["schemas"]["CreatePaymentIntentInput"];
517
563
  customerCreateAttributes: components["schemas"]["CreateCustomerInput"];
518
- }) => Promise<components["schemas"]["EmbedToken"]["token"]>;
519
- onResult: (result: ConfirmationResult) => void;
564
+ confirmPayment: (token: string) => Promise<ConfirmResult>;
565
+ }) => Promise<ConfirmResult>;
520
566
  };
521
567
 
522
568
  /**
@@ -532,8 +578,7 @@ export function AmosApplePayButton({
532
578
  height = "48px",
533
579
  buttonProps,
534
580
  iframeProps,
535
- onInitiatePaymentIntentRequest,
536
- onResult,
581
+ onConfirm,
537
582
  }: AmosApplePayButtonProps) {
538
583
  const containerRef = useRef<HTMLDivElement | null>(null);
539
584
  const borderRadius = resolveWalletButtonSkeletonBorderRadius({
@@ -551,19 +596,11 @@ export function AmosApplePayButton({
551
596
  merchantName,
552
597
  height,
553
598
  buttonProps,
554
- onInitiatePaymentIntentRequest,
555
- onResult,
599
+ onConfirm,
556
600
  },
557
601
  remountDeps: [renderToken],
558
602
  iframePassthrough: iframeProps ?? {},
559
- updateDeps: [
560
- amount,
561
- merchantName,
562
- height,
563
- buttonProps,
564
- onInitiatePaymentIntentRequest,
565
- onResult,
566
- ],
603
+ updateDeps: [amount, merchantName, height, buttonProps, onConfirm],
567
604
  });
568
605
 
569
606
  return (