@amos.com/react-amos-js 0.11.29 → 0.12.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
@@ -16,7 +16,7 @@ npm install @amos.com/react-amos-js @amos.com/node
16
16
 
17
17
  - React components for the iframe payment method forms: `AmosCreditCardPaymentMethodForm`, `AmosBankAccountPaymentMethodForm`, `AmosGooglePayButton`, `AmosApplePayButton`.
18
18
  - React-flavoured iframe message helpers that accept a React `ref`: `validateForm({ iframeRef })`, `confirmPayment({ iframeRef, token })`, `confirmSetup({ iframeRef, token })`, `resetForm({ iframeRef })`, `focusField({ iframeRef, field })`.
19
- - Re-exports of the `@amos.com/amos-js` helpers and types that come up in client code: `createMessage`, `decodeJwt`, `getEmbedOrigin`, `formatGooglePayPaymentData`, `resetForm`, `focusField`, `ConfirmPaymentResult`, `ConfirmSetupResult`, `FormattedGooglePayPaymentData`, `WalletCustomerCreateAttributes`, `WalletPostalAddress`, `WalletContactRequirements`, `Appearance`, `FontSource`, `AppearanceRuleSelector`, `Message`, `PaymentMethodFormDefaultValues`, `PaymentMethodFormField`, etc.
19
+ - Re-exports of the `@amos.com/amos-js` helpers and types that come up in client code: `createMessage`, `decodeJwt`, `getEmbedOrigin`, `formatGooglePayPaymentData`, `resetForm`, `focusField`, `openPlaidPopupLink`, `plaidAccountIdFromMetadata`, `ConfirmPaymentResult`, `ConfirmSetupResult`, `FormattedGooglePayPaymentData`, `WalletCustomerCreateAttributes`, `WalletPostalAddress`, `WalletContactRequirements`, `Appearance`, `FontSource`, `AppearanceRuleSelector`, `Message`, `PaymentMethodFormDefaultValues`, `PaymentMethodFormField`, `ExternalBankAccountConfirmResult`, `ExternalBankAccountScreen`, 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
 
@@ -293,7 +293,7 @@ function CheckoutForm() {
293
293
  renderToken="the-render-token-that-you-created-on-dashboard.amos.com"
294
294
  additionalFields={{ cardholderName: true }}
295
295
  defaultValues={{
296
- name: "Jane Doe",
296
+ cardholderName: "Jane Doe",
297
297
  billingAddress: {
298
298
  line1: "354 Oyster Point Blvd",
299
299
  city: "South San Francisco",
@@ -574,7 +574,7 @@ Renders the secure credit card iframe form. A field-shaped skeleton with an opaq
574
574
 
575
575
  - `additionalFields` (`{ cardholderName: boolean }`) — set `additionalFields={{ cardholderName: true }}` to render the cardholder name field in the iframe (`false` by default)
576
576
  - `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.
577
- - `defaultValues` (`{ name?: string; billingAddress?: { line1?, line2?, city?, state?, postalCode?, country? } }`) — seed cardholder / account-holder name and billing address. Provided keys overwrite matching fields, including ones the customer already edited. Values are also sent on confirm even when those inputs are hidden (cardholder name off, or `country` billing mode). Never send PAN, CVC, account number, or routing number.
577
+ - `defaultValues` (`{ accountHolderName?: string; cardholderName?: string; billingAddress?: { name?, email?, phone?, line1?, line2?, city?, state?, postalCode?, country? } }`) — seed account-holder name, cardholder name, and billing address. Provided keys overwrite matching fields, including ones the customer already edited. `cardholderName` is applied and confirmed only when that input is shown. Billing fields are sent on confirm even when those inputs are hidden (`country` billing mode). Never send PAN, CVC, account number, or routing number.
578
578
  - `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.
579
579
  - `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.
580
580
  - `onPostalCodeChange` (`(event: { postalCode: string | null; country: string }) => void`) — called when the customer commits a billing postal code, or clears one. `postalCode` is a finished code, or `null` when a finished code is deleted or the country changes. Incomplete keystrokes are not reported. US and PR commit at 5 digits (ZIP+4 is reported as the first 5). Canada commits as `A1A 1A1`. The UK commits at a full postcode. Not called for `defaultValues`, so a host can copy its own postal field into the iframe until the first callback and then stop. Debounce shipping-rate requests in the host. Card and bank forms only.
@@ -590,6 +590,8 @@ Renders the secure bank account iframe form. A field-shaped skeleton with an opa
590
590
 
591
591
  When `requireAchVerification` is true (or `intent` is `"setup"`), and the render token allows verification, the SDK hides the routing/account iframe and mounts [Plaid Embedded Institution Search](https://plaid.com/docs/link/embedded-institution-search/) in the parent. A **350px pulse skeleton** covers that slot until Plaid's `onLoad` (1.5s fallback). Do not overlay a host loader. Hosts do not proxy Pay API (`POST /plaid_link_tokens`); embed does that with `PAY_API_KEY`. Do not put Plaid secrets in the browser.
592
592
 
593
+ **Two kinds of Plaid session.** `requireAchVerification` and `intent="setup"` only ever mount **Embedded Institution Search**. Re-entering a connection the customer already added — typing micro-deposit codes — is a **regular** Link session, and Plaid forbids Embedded Institution Search in update mode entirely, which is why the SDK exposes it as a separate call (`openPlaidPopupLink`) instead of another prop. Nothing in the React layer listens for `EXTERNAL_BANK_ACCOUNT_LINK_TOKEN` (it carries `linkToken` plus `mode: "new" | "update"`), so a host that drives an external-bank-account intent handles that message itself, opens Link, then posts `CONFIRM_EXTERNAL_BANK_ACCOUNT_INTENT` back to the iframe. There is no React component for that flow yet.
594
+
593
595
  After Link succeeds, Institution Search is replaced by a connected-account row: institution name, masked account (`****` plus last4, or "Connected"), and an outline Disconnect button. Disconnect clears the linked account and shows Institution Search again. The row uses existing `appearance.themeVariables` (`--border`, `--background`, `--foreground`, `--muted` falling back to `--accent`, `--muted-foreground`, `--accent`, `--accent-foreground`, `--radius`, `--ring`). In dark mode the Disconnect border uses `--input`. No new theme variable or appearance rule is required.
594
596
 
595
597
  **Required props:** same as `AmosCreditCardPaymentMethodForm` — `renderToken`.
@@ -702,9 +704,62 @@ Re-export from `@amos.com/amos-js`. Push name and billing-address defaults into
702
704
 
703
705
  Re-export from `@amos.com/amos-js`. Fills omitted Inter `fonts` / `--font-family` (or a system stack when `fonts` is `[]`). The React components call this for you via the mount helpers. Only call it yourself if you are wiring `UPDATE_APPEARANCE` by hand: pass `initial: true` only for the first update after `IFRAME_READY`, and pass the merchant's last `appearance` (so a previous `fonts: []` is not overwritten).
704
706
 
707
+ ### `openPlaidPopupLink({ token, onSuccess, onExit?, signal? })`
708
+
709
+ Re-export from `@amos.com/amos-js`. Opens a **regular** Plaid Link session — the only kind Plaid allows for **update** tokens (micro-deposit re-entry), which Embedded Institution Search cannot open. It loads `https://cdn.plaid.com/link/v2/stable/link-initialize.js` first, then renders Link as an **overlay in your document**, not a browser popup, so awaiting a token before opening does not cost you the user gesture. Despite the name, nothing here is React-specific and `AmosBankAccountPaymentMethodForm` never calls it; use it when you drive the ACH step yourself.
710
+
711
+ **Parameters:**
712
+
713
+ - `token` (`string`, required) — a Plaid link token. The iframe asks for one with `EXTERNAL_BANK_ACCOUNT_LINK_TOKEN`, which also carries `mode: "new" | "update"`; only `update` needs this function.
714
+ - `onSuccess` (`(publicToken, metadata) => void`, required) — forward `publicToken` and `plaidAccountIdFromMetadata(metadata)` to the iframe as `CONFIRM_EXTERNAL_BANK_ACCOUNT_INTENT.plaid` (`{ public_token, account_id }`).
715
+ - `onExit` (`(error: { error_code?: string } | null) => void`, optional) — fires when Link exits (buyer closes it, or a Link-side error); `error_code === "INVALID_LINK_TOKEN"` means the token was stale, so mint another and open a new session.
716
+ - `signal` (`AbortSignal`, optional) — only checked before the session is created and opened; aborting later does not close the overlay, so still call the teardown.
717
+
718
+ **Returns:** `Promise<() => void>` — the teardown. Always call it: destroying the session is what removes the overlay and its `message` listeners, and every call builds a fresh Link frame, so skipping teardown stacks one overlay per session. `open()` throws on a destroyed session, so create a new one per re-entry instead of reusing.
719
+
720
+ ```tsx
721
+ // One Link session per `EXTERNAL_BANK_ACCOUNT_LINK_TOKEN`, torn down when the
722
+ // slot unmounts or a new token arrives.
723
+ useEffect(() => {
724
+ if (!linkToken) {
725
+ return;
726
+ }
727
+
728
+ const controller = new AbortController();
729
+ let unmounted = false;
730
+ let stop: (() => void) | undefined;
731
+
732
+ openPlaidPopupLink({
733
+ token: linkToken,
734
+ signal: controller.signal,
735
+ onSuccess: (publicToken, metadata) => {
736
+ // Post CONFIRM_EXTERNAL_BANK_ACCOUNT_INTENT to the iframe with
737
+ // plaid: { public_token: publicToken, account_id: plaidAccountIdFromMetadata(metadata) }
738
+ },
739
+ }).then(
740
+ (teardown) => {
741
+ if (unmounted) {
742
+ teardown();
743
+ return;
744
+ }
745
+ stop = teardown;
746
+ },
747
+ () => {
748
+ // Plaid never loaded (CSP, offline) — show a retry affordance.
749
+ },
750
+ );
751
+
752
+ return () => {
753
+ unmounted = true;
754
+ controller.abort();
755
+ stop?.();
756
+ };
757
+ }, [linkToken]);
758
+ ```
759
+
705
760
  ### Exported types
706
761
 
707
- `@amos.com/react-amos-js` re-exports everything from `@amos.com/amos-js`, including `ConfirmPaymentResult`, `ConfirmSetupResult`, `isConfirmTimeout`, `CONFIRM_TIMEOUT_MS`, `PAYMENT_IFRAME_SANDBOX`, `WALLET_IFRAME_SANDBOX`, `PaymentMethodFormValidityChangeEvent`, `CardBrand`, `PaymentMethodFormCardBrandChangeEvent`, `PaymentMethodFormPostalCodeChangeEvent`, `FormattedGooglePayPaymentData`, `WalletCustomerCreateAttributes`, `WalletPostalAddress`, `WalletContactRequirements`, `Message`, `Appearance`, `ThemeVariable`, `FontSource`, `CssFontSource`, `CustomFontSource`, `AppearanceRuleSelector`, `AppearanceRuleDeclarations`, `PaymentMethodFormDefaultValues`, `PaymentMethodFormField`, and the per-form `*Options` / `*Controller` types. For OpenAPI schema types (e.g. `PaymentIntent`, `CreatePaymentIntentInput`), import `components` from `@amos.com/node`. Copy `PAYMENT_IFRAME_SANDBOX` or `WALLET_IFRAME_SANDBOX` onto a hand-built iframe before setting `src`.
762
+ `@amos.com/react-amos-js` re-exports everything from `@amos.com/amos-js`, including `ConfirmPaymentResult`, `ConfirmSetupResult`, `isConfirmTimeout`, `CONFIRM_TIMEOUT_MS`, `PAYMENT_IFRAME_SANDBOX`, `WALLET_IFRAME_SANDBOX`, `PaymentMethodFormValidityChangeEvent`, `CardBrand`, `PaymentMethodFormCardBrandChangeEvent`, `PaymentMethodFormPostalCodeChangeEvent`, `FormattedGooglePayPaymentData`, `WalletCustomerCreateAttributes`, `WalletPostalAddress`, `WalletContactRequirements`, `Message`, `Appearance`, `ThemeVariable`, `FontSource`, `CssFontSource`, `CustomFontSource`, `AppearanceRuleSelector`, `AppearanceRuleDeclarations`, `PaymentMethodFormDefaultValues`, `PaymentMethodFormField`, `ExternalBankAccountConfirmResult`, `ExternalBankAccountFailureReason`, `ExternalBankAccountLinkMode`, `ExternalBankAccountScreen`, `ExternalBankAccountState`, `ExternalBankAccountVerificationStatus`, `OpenPlaidPopupLinkInput`, and the per-form `*Options` / `*Controller` types. For OpenAPI schema types (e.g. `PaymentIntent`, `CreatePaymentIntentInput`), import `components` from `@amos.com/node`. Copy `PAYMENT_IFRAME_SANDBOX` or `WALLET_IFRAME_SANDBOX` onto a hand-built iframe before setting `src`.
708
763
 
709
764
  ## Notes and potential gotchas
710
765
 
@@ -716,6 +771,7 @@ Re-export from `@amos.com/amos-js`. Fills omitted Inter `fonts` / `--font-family
716
771
  - **Iframe handshake**: iframe URLs include canonical search params so the embed does not 307. When the host page URL contains `amosDebug=1`, that flag is copied onto the iframe URL. If the document loads but never posts `IFRAME_READY`, the SDK rewrites `src` once with `amosReload`. Appearance is applied after handshake. The iframe stays at opacity 1 under an opaque skeleton, with an explicit pixel width and height, until `UPDATED_APPEARANCE`, or for 1.5s after the postMessage handshake starts (`IFRAME_READY`) if appearance never acks. Embed messages match on origin plus `iframeName` when `contentWindow` identity changes.
717
772
  - **Iframe sandbox**: mount helpers set `sandbox` before `src`. Card and bank frames use `PAYMENT_IFRAME_SANDBOX` (`allow-forms allow-same-origin allow-scripts`). Wallet frames use `WALLET_IFRAME_SANDBOX`, which also allows the payment-sheet popup (`allow-popups allow-popups-to-escape-sandbox`), and set `allow="payment"`. Hand-built iframes should copy the same attribute. Top-level navigation stays blocked. Host `sandbox`, `width`, and `height` props are ignored.
718
773
  - **Plaid Embedded Link (ACH verification)**: load `cdn.plaid.com` from the **parent** document (see CSP on `AmosBankAccountPaymentMethodForm`). Merchants do not proxy Pay API; the bank iframe mints link tokens. Pass `requireAchVerification` when the host wants Plaid, or `intent="setup"` to always show it, unless the render token disables verification. Toggling that prop hides or shows the existing Embedded handler — it does not reload Institution Search. Confirm still goes through the bank iframe so Amos can attach `plaid` to the payment method. While Link loads, the SDK shows a 350px pulse skeleton until `onLoad` (1.5s fallback) — do not overlay a host loader. After success the same slot is a connected-account row (institution name, mask, outline Disconnect) styled with existing `themeVariables`. Disconnect shows Institution Search again.
774
+ - **Update-mode Plaid Link**: the bank component only mounts Embedded Institution Search. Micro-deposit re-entry needs a regular Link session — call `openPlaidPopupLink()` yourself and always run its teardown, or the overlay and its `message` listeners stay behind and stack on the next attempt. Same CSP as the bank form (`script-src`/`frame-src` for `cdn.plaid.com` and `*.plaid.com`); the overlay is a `cdn.plaid.com` iframe in your document, not a window you can close.
719
775
  - **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. **Cancel payment** is available until the buyer authorizes; after that the overlay shows **Completing your payment…** with no Cancel, then hides when `onConfirm` settles. Avoid stacking other fixed UI above it.
720
776
  - **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.
721
777
 
package/dist/index.d.ts CHANGED
@@ -103,8 +103,11 @@ type AmosCreditCardPaymentMethodFormProps = IframePassthroughProps & {
103
103
  billingAddressRequirement?: BillingAddressRequirement;
104
104
  /**
105
105
  * Seed cardholder name and billing address. Provided keys overwrite
106
- * matching fields, including ones the customer already edited. Values
107
- * are sent on confirm even when those inputs are hidden.
106
+ * matching fields, including ones the customer already edited.
107
+ * `cardholderName` prefills the cardholder input and is confirmed only
108
+ * when `additionalFields.cardholderName` is true. Billing fields,
109
+ * including `billingAddress.name`, `email`, and `phone`, are sent on
110
+ * confirm even when those inputs are hidden.
108
111
  */
109
112
  defaultValues?: PaymentMethodFormDefaultValues;
110
113
  };
@@ -138,7 +141,9 @@ type AmosBankAccountPaymentMethodFormProps = IframePassthroughProps & {
138
141
  /**
139
142
  * Seed account holder name and billing address. Provided keys
140
143
  * overwrite matching fields, including ones the customer already
141
- * edited.
144
+ * edited. `accountHolderName` prefills the account-holder input.
145
+ * Billing fields, including `billingAddress.name`, `email`, and
146
+ * `phone`, are sent on confirm even when those inputs are hidden.
142
147
  */
143
148
  defaultValues?: PaymentMethodFormDefaultValues;
144
149
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amos.com/react-amos-js",
3
- "version": "0.11.29",
3
+ "version": "0.12.0",
4
4
  "main": "dist/index.js",
5
5
  "repository": {
6
6
  "type": "git",
@@ -57,7 +57,7 @@
57
57
  "vite-plugin-dts": "5.1.1"
58
58
  },
59
59
  "dependencies": {
60
- "@amos.com/amos-js": "0.11.31",
60
+ "@amos.com/amos-js": "0.12.0",
61
61
  "@types/googlepay": "0.7.13"
62
62
  },
63
63
  "peerDependencies": {
package/src/index.tsx CHANGED
@@ -345,8 +345,11 @@ type AmosCreditCardPaymentMethodFormProps = IframePassthroughProps & {
345
345
  billingAddressRequirement?: BillingAddressRequirement;
346
346
  /**
347
347
  * Seed cardholder name and billing address. Provided keys overwrite
348
- * matching fields, including ones the customer already edited. Values
349
- * are sent on confirm even when those inputs are hidden.
348
+ * matching fields, including ones the customer already edited.
349
+ * `cardholderName` prefills the cardholder input and is confirmed only
350
+ * when `additionalFields.cardholderName` is true. Billing fields,
351
+ * including `billingAddress.name`, `email`, and `phone`, are sent on
352
+ * confirm even when those inputs are hidden.
350
353
  */
351
354
  defaultValues?: PaymentMethodFormDefaultValues;
352
355
  };
@@ -430,7 +433,9 @@ type AmosBankAccountPaymentMethodFormProps = IframePassthroughProps & {
430
433
  /**
431
434
  * Seed account holder name and billing address. Provided keys
432
435
  * overwrite matching fields, including ones the customer already
433
- * edited.
436
+ * edited. `accountHolderName` prefills the account-holder input.
437
+ * Billing fields, including `billingAddress.name`, `email`, and
438
+ * `phone`, are sent on confirm even when those inputs are hidden.
434
439
  */
435
440
  defaultValues?: PaymentMethodFormDefaultValues;
436
441
  /**