@amos.com/amos-js 0.9.11 → 0.9.13
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 +22 -7
- package/dist/form-skeleton.d.ts +20 -0
- package/dist/index.js +64 -1
- package/dist/index.mjs +196 -62
- package/dist/mount.d.ts +6 -0
- package/dist/types.d.ts +14 -0
- package/package.json +1 -1
- package/src/apple-pay.ts +1 -0
- package/src/form-skeleton.ts +244 -0
- package/src/google-pay.ts +1 -0
- package/src/mount.ts +180 -40
- package/src/types.ts +20 -0
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ npm install @amos.com/amos-js
|
|
|
14
14
|
|
|
15
15
|
- **Types** for the `postMessage` protocol used between your page and the Amos iframe (`Message`, `Appearance`, `ThemeVariable`). OpenAPI schema types (for example `components["schemas"]["PaymentIntent"]`) come from `@amos.com/node`.
|
|
16
16
|
- **Iframe-targeted helpers** to validate the form, confirm a payment intent, confirm a setup intent, update appearance, etc.
|
|
17
|
-
- **Mount functions** (`mountAmosCreditCardPaymentMethodForm`, `mountAmosBankAccountPaymentMethodForm`, `mountAmosGooglePayButton`, `mountAmosApplePayButton`) that create the iframe, wire up its message protocol, manage its height/opacity, and return a small controller for updating options and tearing it down.
|
|
17
|
+
- **Mount functions** (`mountAmosCreditCardPaymentMethodForm`, `mountAmosBankAccountPaymentMethodForm`, `mountAmosGooglePayButton`, `mountAmosApplePayButton`) that create the iframe, wire up its message protocol, manage its height/opacity, show a field-shaped loading skeleton for card/bank forms, and return a small controller for updating options and tearing it down.
|
|
18
18
|
- **Lower-level building blocks** (`getCreditCardFormSrc`, `attachPaymentMethodFormListeners`, `attachGooglePayButtonListeners`, `attachApplePayButtonListeners`, ...) for integrators (such as `@amos.com/react-amos-js`) that want to render the iframe element themselves.
|
|
19
19
|
|
|
20
20
|
> **Note:** A server-side SDK (for example `@amos.com/node`) must be used alongside `@amos.com/amos-js` for end-to-end payment processing. `@amos.com/amos-js` is the client-side half.
|
|
@@ -96,7 +96,7 @@ form.destroy();
|
|
|
96
96
|
The following flow is for credit card and bank account payment method types only.
|
|
97
97
|
|
|
98
98
|
1. **Set up prerequisites**: create a `renderToken` (safe for client), and keep `apiKey` and `accountId` server-side only.
|
|
99
|
-
2. **Render your checkout UI** by calling `mountAmosCreditCardPaymentMethodForm(container, options)` (or `mountAmosBankAccountPaymentMethodForm(...)`) along with the required `onResult` callback. The
|
|
99
|
+
2. **Render your checkout UI** by calling `mountAmosCreditCardPaymentMethodForm(container, options)` (or `mountAmosBankAccountPaymentMethodForm(...)`) along with the required `onResult` callback. The SDK shows a field-shaped skeleton immediately (sized from `appearance`, `additionalFields`, and `billingAddressRequirement`) and auto-manages iframe height.
|
|
100
100
|
3. **User clicks "Pay now" button**: call `validateForm({ iframe: form.iframe })`, which returns `Promise<true>` if the embedded form is valid, and `Promise<false>` otherwise.
|
|
101
101
|
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.
|
|
102
102
|
5. **Return the payment intent token to the browser**: your backend responds with the embed token (`components["schemas"]["EmbedToken"]`) needed for confirmation.
|
|
@@ -268,13 +268,13 @@ Mount the secure credit-card payment method form into a container element (an `H
|
|
|
268
268
|
|
|
269
269
|
|
|
270
270
|
- `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.
|
|
271
|
-
- `onHeightChange`, `onAppearanceReady` (advanced — override the default iframe styling logic)
|
|
271
|
+
- `onHeightChange`, `onAppearanceReady` (advanced — override the default iframe styling logic). The skeleton is removed and the iframe faded in when `onAppearanceReady` fires.
|
|
272
272
|
|
|
273
273
|
**Returns** `AmosPaymentMethodFormMountController`:
|
|
274
274
|
|
|
275
275
|
- `iframe` — the underlying `<iframe>` element.
|
|
276
276
|
- `update(patch)` — patch any of the options listed above.
|
|
277
|
-
- `destroy()` — remove the iframe and detach listeners.
|
|
277
|
+
- `destroy()` — remove the iframe (and any loading skeleton) and detach listeners.
|
|
278
278
|
|
|
279
279
|
### `mountAmosBankAccountPaymentMethodForm(container, options)`
|
|
280
280
|
|
|
@@ -295,13 +295,28 @@ Mount the secure Google Pay button (express checkout) into a container element.
|
|
|
295
295
|
|
|
296
296
|
**Optional `options`:** `appearance`, `onHeightChange`, `onAppearanceReady`, plus Google Pay button visual options using the same names as `@google-pay/button-react`:
|
|
297
297
|
|
|
298
|
+
- `fullWidth` (`boolean`, defaults to `false`) — fills the mount container without changing the compact default
|
|
298
299
|
- `buttonType` (`"book" | "buy" | "checkout" | "donate" | "order" | "pay" | "plain" | "subscribe" | "short" | "long"`, defaults to `"short"`)
|
|
299
300
|
- `buttonColor` (`"default" | "black" | "white"`)
|
|
300
301
|
- `buttonRadius` (`number`, 0–20)
|
|
301
302
|
- `buttonSizeMode` (`"static" | "fill"`)
|
|
302
303
|
- `buttonLocale` (`string`, e.g. `"en"`)
|
|
303
304
|
- `buttonBorderType` (`"no_border" | "default_border"`)
|
|
304
|
-
- `style` (`{ [property: string]: string | number }`) — applied to the Google Pay button inside the iframe (e.g. `{ height: "48px"
|
|
305
|
+
- `style` (`{ [property: string]: string | number }`) — applied to the Google Pay button inside the iframe (e.g. `{ height: "48px" }`)
|
|
306
|
+
|
|
307
|
+
For a full-width 48px button:
|
|
308
|
+
|
|
309
|
+
```ts
|
|
310
|
+
mountAmosGooglePayButton("#google-pay", {
|
|
311
|
+
// ...required options
|
|
312
|
+
fullWidth: true,
|
|
313
|
+
style: { height: "48px" },
|
|
314
|
+
});
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
The wallet iframe itself is flush with its mount container (`width: 100%`,
|
|
318
|
+
zero margin). `style` targets the button inside that iframe. For advanced host
|
|
319
|
+
layout overrides, use the returned controller's `iframe` element.
|
|
305
320
|
|
|
306
321
|
**Returns** `AmosGooglePayButtonMountController`:
|
|
307
322
|
|
|
@@ -313,6 +328,7 @@ Mount the secure Apple Pay button (express checkout). Same required options and
|
|
|
313
328
|
|
|
314
329
|
**Optional visual options** use Apple's `<apple-pay-button>` attribute names:
|
|
315
330
|
|
|
331
|
+
- `fullWidth` (`boolean`, defaults to `false`) — fills the mount container without changing the compact default
|
|
316
332
|
- `buttonstyle` (`"black" | "white" | "white-outline"`, defaults to `"black"`)
|
|
317
333
|
- `type` (`"plain" | "buy" | "set-up" | "donate" | "check-out" | "book" | "subscribe" | "reload" | "add-money" | "top-up" | "order" | "rent" | "support" | "contribute" | "tip"`, defaults to `"plain"`)
|
|
318
334
|
- `locale` (`string`, BCP 47, defaults to `"en-US"`)
|
|
@@ -320,13 +336,12 @@ Mount the secure Apple Pay button (express checkout). Same required options and
|
|
|
320
336
|
|
|
321
337
|
```ts
|
|
322
338
|
button.update({
|
|
339
|
+
fullWidth: true,
|
|
323
340
|
buttonstyle: "white-outline",
|
|
324
341
|
type: "buy",
|
|
325
342
|
locale: "en-GB",
|
|
326
343
|
style: {
|
|
327
344
|
"--apple-pay-button-height": "48px",
|
|
328
|
-
"--apple-pay-button-width": "100%",
|
|
329
|
-
width: "100%",
|
|
330
345
|
},
|
|
331
346
|
});
|
|
332
347
|
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BillingAddressRequirement, CreditCardAdditionalFields } from './payment-method-form';
|
|
2
|
+
import { Appearance } from './types';
|
|
3
|
+
export type PaymentMethodFormSkeletonKind = "card" | "bank";
|
|
4
|
+
export type PaymentMethodFormSkeletonOptions = {
|
|
5
|
+
kind: PaymentMethodFormSkeletonKind;
|
|
6
|
+
appearance?: Appearance;
|
|
7
|
+
additionalFields?: CreditCardAdditionalFields;
|
|
8
|
+
billingAddressRequirement?: BillingAddressRequirement;
|
|
9
|
+
};
|
|
10
|
+
export type PaymentMethodFormSkeleton = {
|
|
11
|
+
element: HTMLElement;
|
|
12
|
+
update: (options: PaymentMethodFormSkeletonOptions) => void;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Host-page placeholder that mirrors card/bank field layout using the
|
|
16
|
+
* same appearance variables the iframe will apply. Shown immediately
|
|
17
|
+
* while the iframe document loads, then removed when appearance is
|
|
18
|
+
* ready.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createPaymentMethodFormSkeleton(options: PaymentMethodFormSkeletonOptions): PaymentMethodFormSkeleton;
|
package/dist/index.js
CHANGED
|
@@ -1 +1,64 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=`data-amos-apple-pay-waiting`;function t({onCancel:t}){let n=document.querySelector(`[${e}]`);if(n)return n;let r=document.createElement(`div`);r.setAttribute(e,`true`),r.setAttribute(`role`,`dialog`),r.setAttribute(`aria-modal`,`true`),r.setAttribute(`aria-labelledby`,`amos-apple-pay-waiting-title`),Object.assign(r.style,{position:`fixed`,inset:`0`,zIndex:`2147483646`,display:`flex`,alignItems:`center`,justifyContent:`center`,padding:`24px`,boxSizing:`border-box`,background:`rgba(0, 0, 0, 0.55)`,fontFamily:`-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif`});let i=document.createElement(`div`);Object.assign(i.style,{width:`100%`,maxWidth:`360px`,borderRadius:`12px`,background:`#fff`,padding:`28px 24px 20px`,boxSizing:`border-box`,textAlign:`center`,boxShadow:`0 12px 40px rgba(0, 0, 0, 0.25)`});let a=document.createElement(`div`);a.setAttribute(`aria-hidden`,`true`),Object.assign(a.style,{display:`inline-flex`,alignItems:`center`,justifyContent:`center`,gap:`6px`,marginBottom:`16px`,fontSize:`28px`,fontWeight:`600`,letterSpacing:`-0.02em`,color:`#000`,lineHeight:`1`}),a.innerHTML=`<svg width="22" height="26" viewBox="0 0 814 1000" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"/></svg><span>Pay</span>`;let o=document.createElement(`p`);o.id=`amos-apple-pay-waiting-title`,Object.assign(o.style,{margin:`0 0 20px`,fontSize:`15px`,lineHeight:`1.45`,color:`#1a1a1a`}),o.textContent=`Complete your payment in the open Apple Pay window, or close Apple Pay to continue paying another way.`;let s=document.createElement(`button`);return s.type=`button`,s.textContent=`Cancel payment`,Object.assign(s.style,{display:`block`,width:`100%`,border:`none`,borderRadius:`8px`,padding:`12px 16px`,background:`#2c2c2e`,color:`#fff`,fontSize:`15px`,fontWeight:`500`,cursor:`pointer`}),s.addEventListener(`click`,t),i.append(a,o,s),r.append(i),document.body.append(r),r}function n(){document.querySelector(`[${e}]`)?.remove()}function r(e){let[t=``,n=``,r=``]=e?.split(`.`)??[],i=typeof atob==`function`?atob:e=>Buffer.from(e,`base64`).toString(`utf8`);return{header:JSON.parse(i(t)),payload:JSON.parse(i(n)),signature:r}}function i(e){let{env:t=`sandbox`}=r(e).payload;switch(t){case`production`:return`https://embed.amos.com`;case`sandbox`:return`https://embed-sandbox.amos.com`;default:return`https://embed-sandbox.amos.com`}}function a(e){if(!e||typeof e!=`object`)return;let t={};for(let[n,r]of Object.entries(e)){if(typeof r==`string`){if(r.length===0)continue;t[n]=r;continue}typeof r==`number`&&Number.isFinite(r)&&(t[n]=r)}return Object.keys(t).length>0?t:void 0}function o(e){let t={};if(e.buttonstyle!==void 0&&(t.buttonstyle=e.buttonstyle),e.type!==void 0&&(t.type=e.type),e.locale!==void 0&&(t.locale=e.locale),e.style!==void 0){let n=a(e.style);n&&(t.style=n)}return t}function s(e){let t={};if(e.buttonType!==void 0&&(t.buttonType=e.buttonType),e.buttonColor!==void 0&&(t.buttonColor=e.buttonColor),e.buttonRadius!==void 0&&(t.buttonRadius=e.buttonRadius),e.buttonSizeMode!==void 0&&(t.buttonSizeMode=e.buttonSizeMode),e.buttonLocale!==void 0&&(t.buttonLocale=e.buttonLocale),e.buttonBorderType!==void 0&&(t.buttonBorderType=e.buttonBorderType),e.style!==void 0){let n=a(e.style);n&&(t.style=n)}return t}function c(e){return e}function l(e){return new URL(e.src).origin}function u(e){e?.contentWindow&&e.contentWindow.postMessage(c({type:`PARENT_ACKNOWLEDGED_IFRAME_READY`}),l(e))}function d({iframe:e,appearance:t={}}){e?.contentWindow&&e.contentWindow.postMessage(c({type:`UPDATE_APPEARANCE`,appearance:t}),l(e))}function f({iframe:e,props:t}){e?.contentWindow&&e.contentWindow.postMessage(c({type:`UPDATE_APPLE_PAY_BUTTON`,props:o(t)}),l(e))}function p({iframe:e,props:t}){e?.contentWindow&&e.contentWindow.postMessage(c({type:`UPDATE_GOOGLE_PAY_BUTTON`,props:s(t)}),l(e))}function m({iframe:e,amount:t}){e?.contentWindow&&e.contentWindow.postMessage(c({type:`UPDATE_AMOUNT`,amount:t}),l(e))}function h({iframe:e,merchantName:t}){e?.contentWindow&&e.contentWindow.postMessage(c({type:`UPDATE_MERCHANT_NAME`,merchantName:t}),l(e))}function g({iframe:e}){let t=crypto.randomUUID();return new Promise(n=>{e?.contentWindow&&e.contentWindow.postMessage(c({type:`VALIDATE_FORM`,requestId:t}),l(e));let r=setTimeout(()=>{window.removeEventListener(`message`,i),n(!1)},5e3);function i(e){e.data.type===`VALIDATE_FORM`&&e.data.requestId===t&&(window.removeEventListener(`message`,i),clearTimeout(r),n(e.data.isValid??!1))}window.addEventListener(`message`,i)})}function _({iframe:e}){e?.contentWindow&&e.contentWindow.postMessage(c({type:`RESET_FORM`}),l(e))}function v({iframe:e,token:t}){if(!e?.contentWindow)return;let{payment_intent_id:n}=r(t).payload;e.contentWindow.postMessage(c({type:`CONFIRM_PAYMENT_INTENT`,token:t,id:n??void 0}),l(e))}function y({iframe:e,token:t}){if(!e?.contentWindow)return;let{setup_intent_id:n}=r(t).payload;e.contentWindow.postMessage(c({type:`CONFIRM_SETUP_INTENT`,token:t,id:n??void 0}),l(e))}function b({iframe:e,result:t}){e?.contentWindow&&e.contentWindow.postMessage(c({type:`CONFIRMATION_RESULT`,result:t}),l(e))}function x(e){return`${i(e)}/iframe/apple-pay?token=${e}`}function S(){return`40px`}function C(e){e.contentWindow?.postMessage(c({type:`APPLE_PAY_CANCEL`}),l(e))}function w(e,r){let i={...r};function a(){m({iframe:e,amount:i.amount})}function o(){h({iframe:e,merchantName:i.merchantName})}function s(){f({iframe:e,props:i})}function c(r){if(r.source===e.contentWindow)switch(r.data.type){case`IFRAME_READY`:u(e),d({iframe:e,appearance:i.appearance}),a(),o(),s();break;case`UPDATE_HEIGHT`:i.onHeightChange?.(r.data.height);break;case`UPDATE_APPEARANCE`:d({iframe:e,appearance:r.data.appearance});break;case`UPDATED_APPEARANCE`:i.onAppearanceReady?.();break;case`APPLE_PAY_WINDOW_OPEN`:t({onCancel:()=>{C(e),n()}});break;case`APPLE_PAY_WINDOW_CLOSE`:n();break;case`CREATE_PAYMENT_INTENT`:i.onInitiatePaymentIntentRequest({paymentIntentCreateAttributes:r.data.paymentIntentCreateAttributes,customerCreateAttributes:r.data.customerCreateAttributes}).then(t=>{v({iframe:e,token:t})}).catch(e=>{n(),i.onResult({status:`failed`,errorMessage:e instanceof Error?e.message:`Unknown error`})});break;case`CONFIRMATION_RESULT`:n(),i.onResult(r.data.result)}}return window.addEventListener(`message`,c),{update(t){let n=`appearance`in t,r=`amount`in t,c=`merchantName`in t,l=`buttonstyle`in t||`type`in t||`locale`in t||`style`in t;i={...i,...t},n&&d({iframe:e,appearance:i.appearance}),r&&a(),c&&o(),l&&s()},destroy(){window.removeEventListener(`message`,c),n()}}}function T(e){return`${i(e)}/iframe/google-pay?token=${e}`}function E(){return`40px`}function D(e,t){let n={...t};function r(){m({iframe:e,amount:n.amount})}function i(){h({iframe:e,merchantName:n.merchantName})}function a(){p({iframe:e,props:n})}function o(t){if(t.source===e.contentWindow)switch(t.data.type){case`IFRAME_READY`:u(e),d({iframe:e,appearance:n.appearance}),r(),i(),a();break;case`UPDATE_HEIGHT`:n.onHeightChange?.(t.data.height);break;case`UPDATE_APPEARANCE`:d({iframe:e,appearance:t.data.appearance});break;case`UPDATED_APPEARANCE`:n.onAppearanceReady?.();break;case`CREATE_PAYMENT_INTENT`:n.onInitiatePaymentIntentRequest({paymentIntentCreateAttributes:t.data.paymentIntentCreateAttributes,customerCreateAttributes:t.data.customerCreateAttributes}).then(t=>{v({iframe:e,token:t})}).catch(e=>{n.onResult({status:`failed`,errorMessage:e instanceof Error?e.message:`Unknown error`})});break;case`CONFIRMATION_RESULT`:n.onResult(t.data.result)}}return window.addEventListener(`message`,o),{update(t){let o=`appearance`in t,s=`amount`in t,c=`merchantName`in t,l=`buttonType`in t||`buttonColor`in t||`buttonRadius`in t||`buttonSizeMode`in t||`buttonLocale`in t||`buttonBorderType`in t||`style`in t;n={...n,...t},o&&d({iframe:e,appearance:n.appearance}),s&&r(),c&&i(),l&&a()},destroy(){window.removeEventListener(`message`,o)}}}function O({paymentData:e}){return{paymentMethod:{type:`googlepay`,billing_address_attributes:{name:e.shippingAddress?.name,address_line1:e.shippingAddress?.address1,address_line2:e.shippingAddress?.address2,city:e.shippingAddress?.locality,state:e.shippingAddress?.administrativeArea,postal_code:e.shippingAddress?.postalCode,country:e.shippingAddress?.countryCode,email:e.email,phone:e.shippingAddress?.phoneNumber},card_profile_attributes:{wallet_payload:e.paymentMethodData.tokenizationData.token}}}}var k={country:212,full:452},A=80,j={country:400,full:640};function M(e,t={cardholderName:!1},n=`country`){let r=Object.entries(t).filter(([,e])=>e).map(([e])=>e).join(`,`),a=new URLSearchParams({token:e,additionalFields:r,billingAddressRequirement:n});return`${i(e)}/iframe/card?${a}`}function N(e,t=`country`){let n=new URLSearchParams({token:e,billingAddressRequirement:t});return`${i(e)}/iframe/bank?${n}`}function P(e={cardholderName:!1},t=`country`){return`${(k[t]??k.country)+(e.cardholderName?A:0)}px`}function F(e=`country`){return`${j[e]??j.country}px`}function I(e,t){let n={...t};function r(t){if(t.source===e.contentWindow)switch(t.data.type){case`IFRAME_READY`:u(e),d({iframe:e,appearance:n.appearance});break;case`UPDATE_HEIGHT`:n.onHeightChange?.(t.data.height);break;case`UPDATE_APPEARANCE`:d({iframe:e,appearance:t.data.appearance});break;case`UPDATED_APPEARANCE`:n.onAppearanceReady?.();break;case`FORM_VALIDITY_CHANGE`:n.onValidityChange?.({isValid:t.data.isValid});break;case`CONFIRMATION_RESULT`:n.onResult(t.data.result)}}return window.addEventListener(`message`,r),{update(t){let r=`appearance`in t;n={...n,...t},r&&d({iframe:e,appearance:n.appearance})},destroy(){window.removeEventListener(`message`,r)}}}function L(e){if(typeof e==`string`){let t=document.querySelector(e);if(!(t instanceof HTMLElement))throw Error(`[amos-js] Container "${e}" did not match any HTMLElement.`);return t}return e}var R={width:`calc(100% + 8px)`,transition:`opacity 150ms ease-in, height 200ms ease-in-out`,margin:`0 -4px`,opacity:`0`,border:`0`};function z({src:e,title:t,name:n,height:r,allow:i}){let a=document.createElement(`iframe`);return a.src=e,a.title=t,a.name=n,a.setAttribute(`role`,`presentation`),a.scrolling=`no`,i&&(a.allow=i),Object.assign(a.style,R,{height:r}),a}function B(e,t){let n=L(e),{renderToken:r,additionalFields:i={cardholderName:!1},billingAddressRequirement:a=`country`,...o}=t,s=z({src:M(r,i,a),title:`Secure credit card payment method form powered by Amos`,name:`amos-credit-card-payment-method-form`,height:P(i,a)});n.appendChild(s);let c=I(s,{...o,onHeightChange:e=>{s.style.height=e,o.onHeightChange?.(e)},onAppearanceReady:()=>{s.style.opacity=`1`,o.onAppearanceReady?.()}});return{iframe:s,update:c.update,destroy(){c.destroy(),s.remove()}}}function V(e,t){let n=L(e),{renderToken:r,billingAddressRequirement:i=`country`,...a}=t,o=z({src:N(r,i),title:`Secure bank account payment method form powered by Amos`,name:`amos-bank-account-payment-method-form`,height:F(i)});n.appendChild(o);let s=I(o,{...a,onHeightChange:e=>{o.style.height=e,a.onHeightChange?.(e)},onAppearanceReady:()=>{o.style.opacity=`1`,a.onAppearanceReady?.()}});return{iframe:o,update:s.update,destroy(){s.destroy(),o.remove()}}}function H(e,t){let n=L(e),{renderToken:r,...i}=t,a=z({src:T(r),title:`Secure Google Pay button powered by Amos`,name:`amos-google-pay-button`,height:E(),allow:`payment`});n.appendChild(a);let o=D(a,{...i,onHeightChange:e=>{a.style.height=e,i.onHeightChange?.(e)},onAppearanceReady:()=>{a.style.opacity=`1`,i.onAppearanceReady?.()}});return{iframe:a,update:o.update,destroy(){o.destroy(),a.remove()}}}function U(e,t){let n=L(e),{renderToken:r,...i}=t,a=z({src:x(r),title:`Secure Apple Pay button powered by Amos`,name:`amos-apple-pay-button`,height:S(),allow:`payment`});n.appendChild(a);let o=w(a,{...i,onHeightChange:e=>{a.style.height=e,i.onHeightChange?.(e)},onAppearanceReady:()=>{a.style.opacity=`1`,i.onAppearanceReady?.()}});return{iframe:a,update:o.update,destroy(){o.destroy(),a.remove()}}}exports.attachApplePayButtonListeners=w,exports.attachGooglePayButtonListeners=D,exports.attachPaymentMethodFormListeners=I,exports.confirmPaymentIntent=v,exports.confirmSetupIntent=y,exports.createMessage=c,exports.decodeJwt=r,exports.formatGooglePayPaymentData=O,exports.getApplePayButtonInitialHeight=S,exports.getApplePayButtonSrc=x,exports.getBankAccountFormInitialHeight=F,exports.getBankAccountFormSrc=N,exports.getCreditCardFormInitialHeight=P,exports.getCreditCardFormSrc=M,exports.getEmbedOrigin=i,exports.getGooglePayButtonInitialHeight=E,exports.getGooglePayButtonSrc=T,exports.mountAmosApplePayButton=U,exports.mountAmosBankAccountPaymentMethodForm=V,exports.mountAmosCreditCardPaymentMethodForm=B,exports.mountAmosGooglePayButton=H,exports.pickApplePayButtonElementProps=o,exports.pickGooglePayButtonElementProps=s,exports.resetForm=_,exports.sendConfirmationResult=b,exports.sendParentReadyMessage=u,exports.serializeWalletButtonStyle=a,exports.updateAmount=m,exports.updateAppearance=d,exports.updateApplePayButton=f,exports.updateGooglePayButton=p,exports.updateMerchantName=h,exports.validateForm=g;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=`data-amos-apple-pay-waiting`;function t({onCancel:t}){let n=document.querySelector(`[${e}]`);if(n)return n;let r=document.createElement(`div`);r.setAttribute(e,`true`),r.setAttribute(`role`,`dialog`),r.setAttribute(`aria-modal`,`true`),r.setAttribute(`aria-labelledby`,`amos-apple-pay-waiting-title`),Object.assign(r.style,{position:`fixed`,inset:`0`,zIndex:`2147483646`,display:`flex`,alignItems:`center`,justifyContent:`center`,padding:`24px`,boxSizing:`border-box`,background:`rgba(0, 0, 0, 0.55)`,fontFamily:`-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif`});let i=document.createElement(`div`);Object.assign(i.style,{width:`100%`,maxWidth:`360px`,borderRadius:`12px`,background:`#fff`,padding:`28px 24px 20px`,boxSizing:`border-box`,textAlign:`center`,boxShadow:`0 12px 40px rgba(0, 0, 0, 0.25)`});let a=document.createElement(`div`);a.setAttribute(`aria-hidden`,`true`),Object.assign(a.style,{display:`inline-flex`,alignItems:`center`,justifyContent:`center`,gap:`6px`,marginBottom:`16px`,fontSize:`28px`,fontWeight:`600`,letterSpacing:`-0.02em`,color:`#000`,lineHeight:`1`}),a.innerHTML=`<svg width="22" height="26" viewBox="0 0 814 1000" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"/></svg><span>Pay</span>`;let o=document.createElement(`p`);o.id=`amos-apple-pay-waiting-title`,Object.assign(o.style,{margin:`0 0 20px`,fontSize:`15px`,lineHeight:`1.45`,color:`#1a1a1a`}),o.textContent=`Complete your payment in the open Apple Pay window, or close Apple Pay to continue paying another way.`;let s=document.createElement(`button`);return s.type=`button`,s.textContent=`Cancel payment`,Object.assign(s.style,{display:`block`,width:`100%`,border:`none`,borderRadius:`8px`,padding:`12px 16px`,background:`#2c2c2e`,color:`#fff`,fontSize:`15px`,fontWeight:`500`,cursor:`pointer`}),s.addEventListener(`click`,t),i.append(a,o,s),r.append(i),document.body.append(r),r}function n(){document.querySelector(`[${e}]`)?.remove()}function r(e){let[t=``,n=``,r=``]=e?.split(`.`)??[],i=typeof atob==`function`?atob:e=>Buffer.from(e,`base64`).toString(`utf8`);return{header:JSON.parse(i(t)),payload:JSON.parse(i(n)),signature:r}}function i(e){let{env:t=`sandbox`}=r(e).payload;switch(t){case`production`:return`https://embed.amos.com`;case`sandbox`:return`https://embed-sandbox.amos.com`;default:return`https://embed-sandbox.amos.com`}}function a(e){if(!e||typeof e!=`object`)return;let t={};for(let[n,r]of Object.entries(e)){if(typeof r==`string`){if(r.length===0)continue;t[n]=r;continue}typeof r==`number`&&Number.isFinite(r)&&(t[n]=r)}return Object.keys(t).length>0?t:void 0}function o(e){let t={};if(e.fullWidth!==void 0&&(t.fullWidth=e.fullWidth),e.buttonstyle!==void 0&&(t.buttonstyle=e.buttonstyle),e.type!==void 0&&(t.type=e.type),e.locale!==void 0&&(t.locale=e.locale),e.style!==void 0){let n=a(e.style);n&&(t.style=n)}return t}function s(e){let t={};if(e.fullWidth!==void 0&&(t.fullWidth=e.fullWidth),e.buttonType!==void 0&&(t.buttonType=e.buttonType),e.buttonColor!==void 0&&(t.buttonColor=e.buttonColor),e.buttonRadius!==void 0&&(t.buttonRadius=e.buttonRadius),e.buttonSizeMode!==void 0&&(t.buttonSizeMode=e.buttonSizeMode),e.buttonLocale!==void 0&&(t.buttonLocale=e.buttonLocale),e.buttonBorderType!==void 0&&(t.buttonBorderType=e.buttonBorderType),e.style!==void 0){let n=a(e.style);n&&(t.style=n)}return t}function c(e){return e}function l(e){return new URL(e.src).origin}function u(e){e?.contentWindow&&e.contentWindow.postMessage(c({type:`PARENT_ACKNOWLEDGED_IFRAME_READY`}),l(e))}function d({iframe:e,appearance:t={}}){e?.contentWindow&&e.contentWindow.postMessage(c({type:`UPDATE_APPEARANCE`,appearance:t}),l(e))}function f({iframe:e,props:t}){e?.contentWindow&&e.contentWindow.postMessage(c({type:`UPDATE_APPLE_PAY_BUTTON`,props:o(t)}),l(e))}function p({iframe:e,props:t}){e?.contentWindow&&e.contentWindow.postMessage(c({type:`UPDATE_GOOGLE_PAY_BUTTON`,props:s(t)}),l(e))}function m({iframe:e,amount:t}){e?.contentWindow&&e.contentWindow.postMessage(c({type:`UPDATE_AMOUNT`,amount:t}),l(e))}function h({iframe:e,merchantName:t}){e?.contentWindow&&e.contentWindow.postMessage(c({type:`UPDATE_MERCHANT_NAME`,merchantName:t}),l(e))}function g({iframe:e}){let t=crypto.randomUUID();return new Promise(n=>{e?.contentWindow&&e.contentWindow.postMessage(c({type:`VALIDATE_FORM`,requestId:t}),l(e));let r=setTimeout(()=>{window.removeEventListener(`message`,i),n(!1)},5e3);function i(e){e.data.type===`VALIDATE_FORM`&&e.data.requestId===t&&(window.removeEventListener(`message`,i),clearTimeout(r),n(e.data.isValid??!1))}window.addEventListener(`message`,i)})}function _({iframe:e}){e?.contentWindow&&e.contentWindow.postMessage(c({type:`RESET_FORM`}),l(e))}function v({iframe:e,token:t}){if(!e?.contentWindow)return;let{payment_intent_id:n}=r(t).payload;e.contentWindow.postMessage(c({type:`CONFIRM_PAYMENT_INTENT`,token:t,id:n??void 0}),l(e))}function y({iframe:e,token:t}){if(!e?.contentWindow)return;let{setup_intent_id:n}=r(t).payload;e.contentWindow.postMessage(c({type:`CONFIRM_SETUP_INTENT`,token:t,id:n??void 0}),l(e))}function b({iframe:e,result:t}){e?.contentWindow&&e.contentWindow.postMessage(c({type:`CONFIRMATION_RESULT`,result:t}),l(e))}function x(e){return`${i(e)}/iframe/apple-pay?token=${e}`}function S(){return`40px`}function C(e){e.contentWindow?.postMessage(c({type:`APPLE_PAY_CANCEL`}),l(e))}function w(e,r){let i={...r};function a(){m({iframe:e,amount:i.amount})}function o(){h({iframe:e,merchantName:i.merchantName})}function s(){f({iframe:e,props:i})}function c(r){if(r.source===e.contentWindow)switch(r.data.type){case`IFRAME_READY`:u(e),d({iframe:e,appearance:i.appearance}),a(),o(),s();break;case`UPDATE_HEIGHT`:i.onHeightChange?.(r.data.height);break;case`UPDATE_APPEARANCE`:d({iframe:e,appearance:r.data.appearance});break;case`UPDATED_APPEARANCE`:i.onAppearanceReady?.();break;case`APPLE_PAY_WINDOW_OPEN`:t({onCancel:()=>{C(e),n()}});break;case`APPLE_PAY_WINDOW_CLOSE`:n();break;case`CREATE_PAYMENT_INTENT`:i.onInitiatePaymentIntentRequest({paymentIntentCreateAttributes:r.data.paymentIntentCreateAttributes,customerCreateAttributes:r.data.customerCreateAttributes}).then(t=>{v({iframe:e,token:t})}).catch(e=>{n(),i.onResult({status:`failed`,errorMessage:e instanceof Error?e.message:`Unknown error`})});break;case`CONFIRMATION_RESULT`:n(),i.onResult(r.data.result)}}return window.addEventListener(`message`,c),{update(t){let n=`appearance`in t,r=`amount`in t,c=`merchantName`in t,l=`fullWidth`in t||`buttonstyle`in t||`type`in t||`locale`in t||`style`in t;i={...i,...t},n&&d({iframe:e,appearance:i.appearance}),r&&a(),c&&o(),l&&s()},destroy(){window.removeEventListener(`message`,c),n()}}}function T(e){return`${i(e)}/iframe/google-pay?token=${e}`}function E(){return`40px`}function D(e,t){let n={...t};function r(){m({iframe:e,amount:n.amount})}function i(){h({iframe:e,merchantName:n.merchantName})}function a(){p({iframe:e,props:n})}function o(t){if(t.source===e.contentWindow)switch(t.data.type){case`IFRAME_READY`:u(e),d({iframe:e,appearance:n.appearance}),r(),i(),a();break;case`UPDATE_HEIGHT`:n.onHeightChange?.(t.data.height);break;case`UPDATE_APPEARANCE`:d({iframe:e,appearance:t.data.appearance});break;case`UPDATED_APPEARANCE`:n.onAppearanceReady?.();break;case`CREATE_PAYMENT_INTENT`:n.onInitiatePaymentIntentRequest({paymentIntentCreateAttributes:t.data.paymentIntentCreateAttributes,customerCreateAttributes:t.data.customerCreateAttributes}).then(t=>{v({iframe:e,token:t})}).catch(e=>{n.onResult({status:`failed`,errorMessage:e instanceof Error?e.message:`Unknown error`})});break;case`CONFIRMATION_RESULT`:n.onResult(t.data.result)}}return window.addEventListener(`message`,o),{update(t){let o=`appearance`in t,s=`amount`in t,c=`merchantName`in t,l=`fullWidth`in t||`buttonType`in t||`buttonColor`in t||`buttonRadius`in t||`buttonSizeMode`in t||`buttonLocale`in t||`buttonBorderType`in t||`style`in t;n={...n,...t},o&&d({iframe:e,appearance:n.appearance}),s&&r(),c&&i(),l&&a()},destroy(){window.removeEventListener(`message`,o)}}}function O({paymentData:e}){return{paymentMethod:{type:`googlepay`,billing_address_attributes:{name:e.shippingAddress?.name,address_line1:e.shippingAddress?.address1,address_line2:e.shippingAddress?.address2,city:e.shippingAddress?.locality,state:e.shippingAddress?.administrativeArea,postal_code:e.shippingAddress?.postalCode,country:e.shippingAddress?.countryCode,email:e.email,phone:e.shippingAddress?.phoneNumber},card_profile_attributes:{wallet_payload:e.paymentMethodData.tokenizationData.token}}}}var k=`amos-js-form-skeleton-styles`,A={"--accent":`oklch(0.97 0 0)`,"--radius":`0.625rem`,"--input-height":`2.25rem`,"--floating-input-height":`3.25rem`,"--field-gap":`1rem`,"--control-gap":`0.5rem`,"--label-font-size":`0.875rem`},j=`
|
|
2
|
+
.amos-js-form-skeleton {
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
container-type: inline-size;
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
gap: var(--field-gap);
|
|
8
|
+
margin: 0 -4px;
|
|
9
|
+
padding-block: 0.25rem;
|
|
10
|
+
pointer-events: none;
|
|
11
|
+
width: calc(100% + 8px);
|
|
12
|
+
}
|
|
13
|
+
.amos-js-form-skeleton-field {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex: 1 1 0;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
min-width: 0;
|
|
18
|
+
width: 100%;
|
|
19
|
+
}
|
|
20
|
+
.amos-js-form-skeleton-label {
|
|
21
|
+
flex-shrink: 0;
|
|
22
|
+
font-size: var(--label-font-size);
|
|
23
|
+
height: 1.75rem;
|
|
24
|
+
line-height: 1.75rem;
|
|
25
|
+
}
|
|
26
|
+
.amos-js-form-skeleton-input {
|
|
27
|
+
animation: amos-js-skeleton-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
28
|
+
background: var(--accent);
|
|
29
|
+
border-radius: calc(var(--radius) * 0.8);
|
|
30
|
+
box-sizing: border-box;
|
|
31
|
+
height: var(--input-height);
|
|
32
|
+
width: 100%;
|
|
33
|
+
}
|
|
34
|
+
.amos-js-form-skeleton-input-floating {
|
|
35
|
+
height: var(--floating-input-height);
|
|
36
|
+
}
|
|
37
|
+
.amos-js-form-skeleton-row {
|
|
38
|
+
align-items: flex-start;
|
|
39
|
+
display: flex;
|
|
40
|
+
gap: var(--control-gap);
|
|
41
|
+
width: 100%;
|
|
42
|
+
}
|
|
43
|
+
.amos-js-form-skeleton-row-stack {
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-direction: column;
|
|
46
|
+
gap: var(--field-gap);
|
|
47
|
+
width: 100%;
|
|
48
|
+
}
|
|
49
|
+
@container (min-width: 24rem) {
|
|
50
|
+
.amos-js-form-skeleton-row-stack {
|
|
51
|
+
align-items: flex-start;
|
|
52
|
+
flex-direction: row;
|
|
53
|
+
gap: var(--control-gap);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
@keyframes amos-js-skeleton-pulse {
|
|
57
|
+
50% { opacity: 0.5; }
|
|
58
|
+
}
|
|
59
|
+
@media (prefers-reduced-motion: reduce) {
|
|
60
|
+
.amos-js-form-skeleton-input {
|
|
61
|
+
animation: none;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
`;function M(){if(document.getElementById(k))return;let e=document.createElement(`style`);e.id=k,e.textContent=j,document.head.appendChild(e)}function N(e,t){for(let[t,n]of Object.entries(A))e.style.setProperty(t,n);let n=t?.themeVariables;if(n)for(let[t,r]of Object.entries(n))typeof r==`string`&&r.trim()!==``&&e.style.setProperty(t,r.trim())}function P(e,t){let n=document.createElement(`div`);if(n.className=e,t)for(let e of t)n.appendChild(e);return n}function F(e,t){let n=P(`amos-js-form-skeleton-field`);t!==void 0&&(n.style.flexGrow=String(t)),e===`above`&&n.appendChild(P(`amos-js-form-skeleton-label`));let r=P(`amos-js-form-skeleton-input`);return e===`floating`&&r.classList.add(`amos-js-form-skeleton-input-floating`),n.appendChild(r),n}function I(e,t){return P(t?`amos-js-form-skeleton-row-stack`:`amos-js-form-skeleton-row`,e)}function L({labels:e,requirement:t,wrapCountryZip:n}){return t===`full`?[F(e),F(e),I([F(e,1.4),F(e,.7),F(e,.8)],!1),F(e)]:[I([F(e),F(e)],n)]}function R(e){let t=e.appearance?.labels??`above`,n=e.billingAddressRequirement??`country`;if(e.kind===`card`){let r=[F(t),I([F(t),F(t)],!1)];return e.additionalFields?.cardholderName&&r.push(F(t)),r.push(...L({labels:t,requirement:n,wrapCountryZip:!1})),r}return[F(t),I([F(t),F(t)],!0),F(t),I([F(`above`),F(`above`)],!0),...L({labels:t,requirement:n,wrapCountryZip:!0})]}function z(e){M();let t=P(`amos-js-form-skeleton`);t.setAttribute(`aria-hidden`,`true`);function n(e){N(t,e.appearance),t.replaceChildren(...R(e))}return n(e),{element:t,update:n}}var B={country:212,full:452},V=80,H={country:400,full:640};function U(e,t={cardholderName:!1},n=`country`){let r=Object.entries(t).filter(([,e])=>e).map(([e])=>e).join(`,`),a=new URLSearchParams({token:e,additionalFields:r,billingAddressRequirement:n});return`${i(e)}/iframe/card?${a}`}function W(e,t=`country`){let n=new URLSearchParams({token:e,billingAddressRequirement:t});return`${i(e)}/iframe/bank?${n}`}function G(e={cardholderName:!1},t=`country`){return`${(B[t]??B.country)+(e.cardholderName?V:0)}px`}function K(e=`country`){return`${H[e]??H.country}px`}function q(e,t){let n={...t};function r(t){if(t.source===e.contentWindow)switch(t.data.type){case`IFRAME_READY`:u(e),d({iframe:e,appearance:n.appearance});break;case`UPDATE_HEIGHT`:n.onHeightChange?.(t.data.height);break;case`UPDATE_APPEARANCE`:d({iframe:e,appearance:t.data.appearance});break;case`UPDATED_APPEARANCE`:n.onAppearanceReady?.();break;case`FORM_VALIDITY_CHANGE`:n.onValidityChange?.({isValid:t.data.isValid});break;case`CONFIRMATION_RESULT`:n.onResult(t.data.result)}}return window.addEventListener(`message`,r),{update(t){let r=`appearance`in t;n={...n,...t},r&&d({iframe:e,appearance:n.appearance})},destroy(){window.removeEventListener(`message`,r)}}}function J(e){if(typeof e==`string`){let t=document.querySelector(e);if(!(t instanceof HTMLElement))throw Error(`[amos-js] Container "${e}" did not match any HTMLElement.`);return t}return e}var Y={width:`calc(100% + 8px)`,transition:`opacity 150ms ease-in, height 200ms ease-in-out`,margin:`0 -4px`,opacity:`0`,border:`0`},X={width:`100%`,transition:`height 200ms ease-in-out`,margin:`0`,opacity:`0`,border:`0`},Z={position:`absolute`,top:`0`,left:`-4px`,width:`calc(100% + 8px)`,height:`100%`,margin:`0`,transition:`none`,pointerEvents:`none`};function Q({src:e,title:t,name:n,height:r,allow:i,style:a=Y}){let o=document.createElement(`iframe`);return o.src=e,o.title=t,o.name=n,o.setAttribute(`role`,`presentation`),o.scrolling=`no`,i&&(o.allow=i),Object.assign(o.style,a,{height:r}),o}function $({host:e,iframe:t,listenerOptions:n,skeletonOptions:r}){let i=document.createElement(`div`);i.style.position=`relative`,i.style.width=`100%`,i.setAttribute(`aria-busy`,`true`);let a=z(r);Object.assign(t.style,Z),i.append(a.element,t),e.appendChild(i);let o=!1,s=!1,c,l=r.appearance,u,d;function f(){return i.getBoundingClientRect().height}function p(){return c?Number.parseFloat(c):NaN}function m(){if(o)return;o=!0,d!==void 0&&(clearTimeout(d),d=void 0);let e=f(),n=p(),r=Number.isFinite(n)?Math.max(n,e):e;t.style.transition=`none`,t.style.position=``,t.style.top=``,t.style.left=``,t.style.margin=Y.margin??``,t.style.height=`${r}px`,t.style.opacity=`1`,t.style.pointerEvents=``,a.element.remove(),i.removeAttribute(`aria-busy`),u=setTimeout(()=>{t.style.transition=`height 200ms ease-in-out`},400)}function h(){if(o||!s)return;let e=p(),t=f();Number.isFinite(e)&&e>=t-2&&m()}let g=q(t,{...n,onHeightChange:e=>{c=e,o?t.style.height=e:h(),n.onHeightChange?.(e)},onAppearanceReady:()=>{s=!0,h(),!o&&d===void 0&&(d=setTimeout(()=>{m()},1500)),n.onAppearanceReady?.()}});return{iframe:t,update(e){g.update(e),!o&&`appearance`in e&&(l=e.appearance,a.update({...r,appearance:l}))},destroy(){u!==void 0&&clearTimeout(u),d!==void 0&&clearTimeout(d),g.destroy(),i.remove()}}}function ee(e,t){let n=J(e),{renderToken:r,additionalFields:i={cardholderName:!1},billingAddressRequirement:a=`country`,...o}=t;return $({host:n,iframe:Q({src:U(r,i,a),title:`Secure credit card payment method form powered by Amos`,name:`amos-credit-card-payment-method-form`,height:G(i,a)}),listenerOptions:o,skeletonOptions:{kind:`card`,appearance:o.appearance,additionalFields:i,billingAddressRequirement:a}})}function te(e,t){let n=J(e),{renderToken:r,billingAddressRequirement:i=`country`,...a}=t;return $({host:n,iframe:Q({src:W(r,i),title:`Secure bank account payment method form powered by Amos`,name:`amos-bank-account-payment-method-form`,height:K(i)}),listenerOptions:a,skeletonOptions:{kind:`bank`,appearance:a.appearance,billingAddressRequirement:i}})}function ne(e,t){let n=J(e),{renderToken:r,...i}=t,a=Q({src:T(r),title:`Secure Google Pay button powered by Amos`,name:`amos-google-pay-button`,height:E(),allow:`payment`,style:X});n.appendChild(a);let o=D(a,{...i,onHeightChange:e=>{a.style.height=e,i.onHeightChange?.(e)},onAppearanceReady:()=>{a.style.opacity=`1`,i.onAppearanceReady?.()}});return{iframe:a,update:o.update,destroy(){o.destroy(),a.remove()}}}function re(e,t){let n=J(e),{renderToken:r,...i}=t,a=Q({src:x(r),title:`Secure Apple Pay button powered by Amos`,name:`amos-apple-pay-button`,height:S(),allow:`payment`,style:X});n.appendChild(a);let o=w(a,{...i,onHeightChange:e=>{a.style.height=e,i.onHeightChange?.(e)},onAppearanceReady:()=>{a.style.opacity=`1`,i.onAppearanceReady?.()}});return{iframe:a,update:o.update,destroy(){o.destroy(),a.remove()}}}exports.attachApplePayButtonListeners=w,exports.attachGooglePayButtonListeners=D,exports.attachPaymentMethodFormListeners=q,exports.confirmPaymentIntent=v,exports.confirmSetupIntent=y,exports.createMessage=c,exports.decodeJwt=r,exports.formatGooglePayPaymentData=O,exports.getApplePayButtonInitialHeight=S,exports.getApplePayButtonSrc=x,exports.getBankAccountFormInitialHeight=K,exports.getBankAccountFormSrc=W,exports.getCreditCardFormInitialHeight=G,exports.getCreditCardFormSrc=U,exports.getEmbedOrigin=i,exports.getGooglePayButtonInitialHeight=E,exports.getGooglePayButtonSrc=T,exports.mountAmosApplePayButton=re,exports.mountAmosBankAccountPaymentMethodForm=te,exports.mountAmosCreditCardPaymentMethodForm=ee,exports.mountAmosGooglePayButton=ne,exports.pickApplePayButtonElementProps=o,exports.pickGooglePayButtonElementProps=s,exports.resetForm=_,exports.sendConfirmationResult=b,exports.sendParentReadyMessage=u,exports.serializeWalletButtonStyle=a,exports.updateAmount=m,exports.updateAppearance=d,exports.updateApplePayButton=f,exports.updateGooglePayButton=p,exports.updateMerchantName=h,exports.validateForm=g;
|
package/dist/index.mjs
CHANGED
|
@@ -99,7 +99,7 @@ function a(e) {
|
|
|
99
99
|
}
|
|
100
100
|
function o(e) {
|
|
101
101
|
let t = {};
|
|
102
|
-
if (e.buttonstyle !== void 0 && (t.buttonstyle = e.buttonstyle), e.type !== void 0 && (t.type = e.type), e.locale !== void 0 && (t.locale = e.locale), e.style !== void 0) {
|
|
102
|
+
if (e.fullWidth !== void 0 && (t.fullWidth = e.fullWidth), e.buttonstyle !== void 0 && (t.buttonstyle = e.buttonstyle), e.type !== void 0 && (t.type = e.type), e.locale !== void 0 && (t.locale = e.locale), e.style !== void 0) {
|
|
103
103
|
let n = a(e.style);
|
|
104
104
|
n && (t.style = n);
|
|
105
105
|
}
|
|
@@ -107,7 +107,7 @@ function o(e) {
|
|
|
107
107
|
}
|
|
108
108
|
function s(e) {
|
|
109
109
|
let t = {};
|
|
110
|
-
if (e.buttonType !== void 0 && (t.buttonType = e.buttonType), e.buttonColor !== void 0 && (t.buttonColor = e.buttonColor), e.buttonRadius !== void 0 && (t.buttonRadius = e.buttonRadius), e.buttonSizeMode !== void 0 && (t.buttonSizeMode = e.buttonSizeMode), e.buttonLocale !== void 0 && (t.buttonLocale = e.buttonLocale), e.buttonBorderType !== void 0 && (t.buttonBorderType = e.buttonBorderType), e.style !== void 0) {
|
|
110
|
+
if (e.fullWidth !== void 0 && (t.fullWidth = e.fullWidth), e.buttonType !== void 0 && (t.buttonType = e.buttonType), e.buttonColor !== void 0 && (t.buttonColor = e.buttonColor), e.buttonRadius !== void 0 && (t.buttonRadius = e.buttonRadius), e.buttonSizeMode !== void 0 && (t.buttonSizeMode = e.buttonSizeMode), e.buttonLocale !== void 0 && (t.buttonLocale = e.buttonLocale), e.buttonBorderType !== void 0 && (t.buttonBorderType = e.buttonBorderType), e.style !== void 0) {
|
|
111
111
|
let n = a(e.style);
|
|
112
112
|
n && (t.style = n);
|
|
113
113
|
}
|
|
@@ -277,7 +277,7 @@ function w(e, r) {
|
|
|
277
277
|
}
|
|
278
278
|
return window.addEventListener("message", c), {
|
|
279
279
|
update(t) {
|
|
280
|
-
let n = "appearance" in t, r = "amount" in t, c = "merchantName" in t, l = "buttonstyle" in t || "type" in t || "locale" in t || "style" in t;
|
|
280
|
+
let n = "appearance" in t, r = "amount" in t, c = "merchantName" in t, l = "fullWidth" in t || "buttonstyle" in t || "type" in t || "locale" in t || "style" in t;
|
|
281
281
|
i = {
|
|
282
282
|
...i,
|
|
283
283
|
...t
|
|
@@ -360,7 +360,7 @@ function D(e, t) {
|
|
|
360
360
|
}
|
|
361
361
|
return window.addEventListener("message", o), {
|
|
362
362
|
update(t) {
|
|
363
|
-
let o = "appearance" in t, s = "amount" in t, c = "merchantName" in t, l = "buttonType" in t || "buttonColor" in t || "buttonRadius" in t || "buttonSizeMode" in t || "buttonLocale" in t || "buttonBorderType" in t || "style" in t;
|
|
363
|
+
let o = "appearance" in t, s = "amount" in t, c = "merchantName" in t, l = "fullWidth" in t || "buttonType" in t || "buttonColor" in t || "buttonRadius" in t || "buttonSizeMode" in t || "buttonLocale" in t || "buttonBorderType" in t || "style" in t;
|
|
364
364
|
n = {
|
|
365
365
|
...n,
|
|
366
366
|
...t
|
|
@@ -392,15 +392,96 @@ function O({ paymentData: e }) {
|
|
|
392
392
|
} };
|
|
393
393
|
}
|
|
394
394
|
//#endregion
|
|
395
|
+
//#region src/form-skeleton.ts
|
|
396
|
+
var k = "amos-js-form-skeleton-styles", A = {
|
|
397
|
+
"--accent": "oklch(0.97 0 0)",
|
|
398
|
+
"--radius": "0.625rem",
|
|
399
|
+
"--input-height": "2.25rem",
|
|
400
|
+
"--floating-input-height": "3.25rem",
|
|
401
|
+
"--field-gap": "1rem",
|
|
402
|
+
"--control-gap": "0.5rem",
|
|
403
|
+
"--label-font-size": "0.875rem"
|
|
404
|
+
}, j = "\n.amos-js-form-skeleton {\n box-sizing: border-box;\n container-type: inline-size;\n display: flex;\n flex-direction: column;\n gap: var(--field-gap);\n margin: 0 -4px;\n padding-block: 0.25rem;\n pointer-events: none;\n width: calc(100% + 8px);\n}\n.amos-js-form-skeleton-field {\n display: flex;\n flex: 1 1 0;\n flex-direction: column;\n min-width: 0;\n width: 100%;\n}\n.amos-js-form-skeleton-label {\n flex-shrink: 0;\n font-size: var(--label-font-size);\n height: 1.75rem;\n line-height: 1.75rem;\n}\n.amos-js-form-skeleton-input {\n animation: amos-js-skeleton-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n background: var(--accent);\n border-radius: calc(var(--radius) * 0.8);\n box-sizing: border-box;\n height: var(--input-height);\n width: 100%;\n}\n.amos-js-form-skeleton-input-floating {\n height: var(--floating-input-height);\n}\n.amos-js-form-skeleton-row {\n align-items: flex-start;\n display: flex;\n gap: var(--control-gap);\n width: 100%;\n}\n.amos-js-form-skeleton-row-stack {\n display: flex;\n flex-direction: column;\n gap: var(--field-gap);\n width: 100%;\n}\n@container (min-width: 24rem) {\n .amos-js-form-skeleton-row-stack {\n align-items: flex-start;\n flex-direction: row;\n gap: var(--control-gap);\n }\n}\n@keyframes amos-js-skeleton-pulse {\n 50% { opacity: 0.5; }\n}\n@media (prefers-reduced-motion: reduce) {\n .amos-js-form-skeleton-input {\n animation: none;\n }\n}\n";
|
|
405
|
+
function M() {
|
|
406
|
+
if (document.getElementById(k)) return;
|
|
407
|
+
let e = document.createElement("style");
|
|
408
|
+
e.id = k, e.textContent = j, document.head.appendChild(e);
|
|
409
|
+
}
|
|
410
|
+
function N(e, t) {
|
|
411
|
+
for (let [t, n] of Object.entries(A)) e.style.setProperty(t, n);
|
|
412
|
+
let n = t?.themeVariables;
|
|
413
|
+
if (n) for (let [t, r] of Object.entries(n)) typeof r == "string" && r.trim() !== "" && e.style.setProperty(t, r.trim());
|
|
414
|
+
}
|
|
415
|
+
function P(e, t) {
|
|
416
|
+
let n = document.createElement("div");
|
|
417
|
+
if (n.className = e, t) for (let e of t) n.appendChild(e);
|
|
418
|
+
return n;
|
|
419
|
+
}
|
|
420
|
+
function F(e, t) {
|
|
421
|
+
let n = P("amos-js-form-skeleton-field");
|
|
422
|
+
t !== void 0 && (n.style.flexGrow = String(t)), e === "above" && n.appendChild(P("amos-js-form-skeleton-label"));
|
|
423
|
+
let r = P("amos-js-form-skeleton-input");
|
|
424
|
+
return e === "floating" && r.classList.add("amos-js-form-skeleton-input-floating"), n.appendChild(r), n;
|
|
425
|
+
}
|
|
426
|
+
function I(e, t) {
|
|
427
|
+
return P(t ? "amos-js-form-skeleton-row-stack" : "amos-js-form-skeleton-row", e);
|
|
428
|
+
}
|
|
429
|
+
function L({ labels: e, requirement: t, wrapCountryZip: n }) {
|
|
430
|
+
return t === "full" ? [
|
|
431
|
+
F(e),
|
|
432
|
+
F(e),
|
|
433
|
+
I([
|
|
434
|
+
F(e, 1.4),
|
|
435
|
+
F(e, .7),
|
|
436
|
+
F(e, .8)
|
|
437
|
+
], !1),
|
|
438
|
+
F(e)
|
|
439
|
+
] : [I([F(e), F(e)], n)];
|
|
440
|
+
}
|
|
441
|
+
function R(e) {
|
|
442
|
+
let t = e.appearance?.labels ?? "above", n = e.billingAddressRequirement ?? "country";
|
|
443
|
+
if (e.kind === "card") {
|
|
444
|
+
let r = [F(t), I([F(t), F(t)], !1)];
|
|
445
|
+
return e.additionalFields?.cardholderName && r.push(F(t)), r.push(...L({
|
|
446
|
+
labels: t,
|
|
447
|
+
requirement: n,
|
|
448
|
+
wrapCountryZip: !1
|
|
449
|
+
})), r;
|
|
450
|
+
}
|
|
451
|
+
return [
|
|
452
|
+
F(t),
|
|
453
|
+
I([F(t), F(t)], !0),
|
|
454
|
+
F(t),
|
|
455
|
+
I([F("above"), F("above")], !0),
|
|
456
|
+
...L({
|
|
457
|
+
labels: t,
|
|
458
|
+
requirement: n,
|
|
459
|
+
wrapCountryZip: !0
|
|
460
|
+
})
|
|
461
|
+
];
|
|
462
|
+
}
|
|
463
|
+
function z(e) {
|
|
464
|
+
M();
|
|
465
|
+
let t = P("amos-js-form-skeleton");
|
|
466
|
+
t.setAttribute("aria-hidden", "true");
|
|
467
|
+
function n(e) {
|
|
468
|
+
N(t, e.appearance), t.replaceChildren(...R(e));
|
|
469
|
+
}
|
|
470
|
+
return n(e), {
|
|
471
|
+
element: t,
|
|
472
|
+
update: n
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
//#endregion
|
|
395
476
|
//#region src/payment-method-form.ts
|
|
396
|
-
var
|
|
477
|
+
var B = {
|
|
397
478
|
country: 212,
|
|
398
479
|
full: 452
|
|
399
|
-
},
|
|
480
|
+
}, V = 80, H = {
|
|
400
481
|
country: 400,
|
|
401
482
|
full: 640
|
|
402
483
|
};
|
|
403
|
-
function
|
|
484
|
+
function U(e, t = { cardholderName: !1 }, n = "country") {
|
|
404
485
|
let r = Object.entries(t).filter(([, e]) => e).map(([e]) => e).join(","), a = new URLSearchParams({
|
|
405
486
|
token: e,
|
|
406
487
|
additionalFields: r,
|
|
@@ -408,20 +489,20 @@ function M(e, t = { cardholderName: !1 }, n = "country") {
|
|
|
408
489
|
});
|
|
409
490
|
return `${i(e)}/iframe/card?${a}`;
|
|
410
491
|
}
|
|
411
|
-
function
|
|
492
|
+
function W(e, t = "country") {
|
|
412
493
|
let n = new URLSearchParams({
|
|
413
494
|
token: e,
|
|
414
495
|
billingAddressRequirement: t
|
|
415
496
|
});
|
|
416
497
|
return `${i(e)}/iframe/bank?${n}`;
|
|
417
498
|
}
|
|
418
|
-
function
|
|
419
|
-
return `${(
|
|
499
|
+
function G(e = { cardholderName: !1 }, t = "country") {
|
|
500
|
+
return `${(B[t] ?? B.country) + (e.cardholderName ? V : 0)}px`;
|
|
420
501
|
}
|
|
421
|
-
function
|
|
422
|
-
return `${
|
|
502
|
+
function K(e = "country") {
|
|
503
|
+
return `${H[e] ?? H.country}px`;
|
|
423
504
|
}
|
|
424
|
-
function
|
|
505
|
+
function q(e, t) {
|
|
425
506
|
let n = { ...t };
|
|
426
507
|
function r(t) {
|
|
427
508
|
if (t.source === e.contentWindow) switch (t.data.type) {
|
|
@@ -467,7 +548,7 @@ function I(e, t) {
|
|
|
467
548
|
}
|
|
468
549
|
//#endregion
|
|
469
550
|
//#region src/mount.ts
|
|
470
|
-
function
|
|
551
|
+
function J(e) {
|
|
471
552
|
if (typeof e == "string") {
|
|
472
553
|
let t = document.querySelector(e);
|
|
473
554
|
if (!(t instanceof HTMLElement)) throw Error(`[amos-js] Container "${e}" did not match any HTMLElement.`);
|
|
@@ -475,74 +556,126 @@ function L(e) {
|
|
|
475
556
|
}
|
|
476
557
|
return e;
|
|
477
558
|
}
|
|
478
|
-
var
|
|
559
|
+
var Y = {
|
|
479
560
|
width: "calc(100% + 8px)",
|
|
480
561
|
transition: "opacity 150ms ease-in, height 200ms ease-in-out",
|
|
481
562
|
margin: "0 -4px",
|
|
482
563
|
opacity: "0",
|
|
483
564
|
border: "0"
|
|
565
|
+
}, X = {
|
|
566
|
+
width: "100%",
|
|
567
|
+
transition: "height 200ms ease-in-out",
|
|
568
|
+
margin: "0",
|
|
569
|
+
opacity: "0",
|
|
570
|
+
border: "0"
|
|
571
|
+
}, Z = {
|
|
572
|
+
position: "absolute",
|
|
573
|
+
top: "0",
|
|
574
|
+
left: "-4px",
|
|
575
|
+
width: "calc(100% + 8px)",
|
|
576
|
+
height: "100%",
|
|
577
|
+
margin: "0",
|
|
578
|
+
transition: "none",
|
|
579
|
+
pointerEvents: "none"
|
|
484
580
|
};
|
|
485
|
-
function
|
|
486
|
-
let
|
|
487
|
-
return
|
|
488
|
-
}
|
|
489
|
-
function
|
|
490
|
-
let
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
581
|
+
function Q({ src: e, title: t, name: n, height: r, allow: i, style: a = Y }) {
|
|
582
|
+
let o = document.createElement("iframe");
|
|
583
|
+
return o.src = e, o.title = t, o.name = n, o.setAttribute("role", "presentation"), o.scrolling = "no", i && (o.allow = i), Object.assign(o.style, a, { height: r }), o;
|
|
584
|
+
}
|
|
585
|
+
function $({ host: e, iframe: t, listenerOptions: n, skeletonOptions: r }) {
|
|
586
|
+
let i = document.createElement("div");
|
|
587
|
+
i.style.position = "relative", i.style.width = "100%", i.setAttribute("aria-busy", "true");
|
|
588
|
+
let a = z(r);
|
|
589
|
+
Object.assign(t.style, Z), i.append(a.element, t), e.appendChild(i);
|
|
590
|
+
let o = !1, s = !1, c, l = r.appearance, u, d;
|
|
591
|
+
function f() {
|
|
592
|
+
return i.getBoundingClientRect().height;
|
|
593
|
+
}
|
|
594
|
+
function p() {
|
|
595
|
+
return c ? Number.parseFloat(c) : NaN;
|
|
596
|
+
}
|
|
597
|
+
function m() {
|
|
598
|
+
if (o) return;
|
|
599
|
+
o = !0, d !== void 0 && (clearTimeout(d), d = void 0);
|
|
600
|
+
let e = f(), n = p(), r = Number.isFinite(n) ? Math.max(n, e) : e;
|
|
601
|
+
t.style.transition = "none", t.style.position = "", t.style.top = "", t.style.left = "", t.style.margin = Y.margin ?? "", t.style.height = `${r}px`, t.style.opacity = "1", t.style.pointerEvents = "", a.element.remove(), i.removeAttribute("aria-busy"), u = setTimeout(() => {
|
|
602
|
+
t.style.transition = "height 200ms ease-in-out";
|
|
603
|
+
}, 400);
|
|
604
|
+
}
|
|
605
|
+
function h() {
|
|
606
|
+
if (o || !s) return;
|
|
607
|
+
let e = p(), t = f();
|
|
608
|
+
Number.isFinite(e) && e >= t - 2 && m();
|
|
609
|
+
}
|
|
610
|
+
let g = q(t, {
|
|
611
|
+
...n,
|
|
499
612
|
onHeightChange: (e) => {
|
|
500
|
-
|
|
613
|
+
c = e, o ? t.style.height = e : h(), n.onHeightChange?.(e);
|
|
501
614
|
},
|
|
502
615
|
onAppearanceReady: () => {
|
|
503
|
-
s
|
|
616
|
+
s = !0, h(), !o && d === void 0 && (d = setTimeout(() => {
|
|
617
|
+
m();
|
|
618
|
+
}, 1500)), n.onAppearanceReady?.();
|
|
504
619
|
}
|
|
505
620
|
});
|
|
506
621
|
return {
|
|
507
|
-
iframe:
|
|
508
|
-
update
|
|
622
|
+
iframe: t,
|
|
623
|
+
update(e) {
|
|
624
|
+
g.update(e), !o && "appearance" in e && (l = e.appearance, a.update({
|
|
625
|
+
...r,
|
|
626
|
+
appearance: l
|
|
627
|
+
}));
|
|
628
|
+
},
|
|
509
629
|
destroy() {
|
|
510
|
-
|
|
630
|
+
u !== void 0 && clearTimeout(u), d !== void 0 && clearTimeout(d), g.destroy(), i.remove();
|
|
511
631
|
}
|
|
512
632
|
};
|
|
513
633
|
}
|
|
514
|
-
function
|
|
515
|
-
let n =
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
634
|
+
function ee(e, t) {
|
|
635
|
+
let n = J(e), { renderToken: r, additionalFields: i = { cardholderName: !1 }, billingAddressRequirement: a = "country", ...o } = t;
|
|
636
|
+
return $({
|
|
637
|
+
host: n,
|
|
638
|
+
iframe: Q({
|
|
639
|
+
src: U(r, i, a),
|
|
640
|
+
title: "Secure credit card payment method form powered by Amos",
|
|
641
|
+
name: "amos-credit-card-payment-method-form",
|
|
642
|
+
height: G(i, a)
|
|
643
|
+
}),
|
|
644
|
+
listenerOptions: o,
|
|
645
|
+
skeletonOptions: {
|
|
646
|
+
kind: "card",
|
|
647
|
+
appearance: o.appearance,
|
|
648
|
+
additionalFields: i,
|
|
649
|
+
billingAddressRequirement: a
|
|
529
650
|
}
|
|
530
651
|
});
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
652
|
+
}
|
|
653
|
+
function te(e, t) {
|
|
654
|
+
let n = J(e), { renderToken: r, billingAddressRequirement: i = "country", ...a } = t;
|
|
655
|
+
return $({
|
|
656
|
+
host: n,
|
|
657
|
+
iframe: Q({
|
|
658
|
+
src: W(r, i),
|
|
659
|
+
title: "Secure bank account payment method form powered by Amos",
|
|
660
|
+
name: "amos-bank-account-payment-method-form",
|
|
661
|
+
height: K(i)
|
|
662
|
+
}),
|
|
663
|
+
listenerOptions: a,
|
|
664
|
+
skeletonOptions: {
|
|
665
|
+
kind: "bank",
|
|
666
|
+
appearance: a.appearance,
|
|
667
|
+
billingAddressRequirement: i
|
|
536
668
|
}
|
|
537
|
-
};
|
|
669
|
+
});
|
|
538
670
|
}
|
|
539
|
-
function
|
|
540
|
-
let n =
|
|
671
|
+
function ne(e, t) {
|
|
672
|
+
let n = J(e), { renderToken: r, ...i } = t, a = Q({
|
|
541
673
|
src: T(r),
|
|
542
674
|
title: "Secure Google Pay button powered by Amos",
|
|
543
675
|
name: "amos-google-pay-button",
|
|
544
676
|
height: E(),
|
|
545
|
-
allow: "payment"
|
|
677
|
+
allow: "payment",
|
|
678
|
+
style: X
|
|
546
679
|
});
|
|
547
680
|
n.appendChild(a);
|
|
548
681
|
let o = D(a, {
|
|
@@ -562,13 +695,14 @@ function H(e, t) {
|
|
|
562
695
|
}
|
|
563
696
|
};
|
|
564
697
|
}
|
|
565
|
-
function
|
|
566
|
-
let n =
|
|
698
|
+
function re(e, t) {
|
|
699
|
+
let n = J(e), { renderToken: r, ...i } = t, a = Q({
|
|
567
700
|
src: x(r),
|
|
568
701
|
title: "Secure Apple Pay button powered by Amos",
|
|
569
702
|
name: "amos-apple-pay-button",
|
|
570
703
|
height: S(),
|
|
571
|
-
allow: "payment"
|
|
704
|
+
allow: "payment",
|
|
705
|
+
style: X
|
|
572
706
|
});
|
|
573
707
|
n.appendChild(a);
|
|
574
708
|
let o = w(a, {
|
|
@@ -589,4 +723,4 @@ function U(e, t) {
|
|
|
589
723
|
};
|
|
590
724
|
}
|
|
591
725
|
//#endregion
|
|
592
|
-
export { w as attachApplePayButtonListeners, D as attachGooglePayButtonListeners,
|
|
726
|
+
export { w as attachApplePayButtonListeners, D as attachGooglePayButtonListeners, q as attachPaymentMethodFormListeners, v as confirmPaymentIntent, y as confirmSetupIntent, c as createMessage, r as decodeJwt, O as formatGooglePayPaymentData, S as getApplePayButtonInitialHeight, x as getApplePayButtonSrc, K as getBankAccountFormInitialHeight, W as getBankAccountFormSrc, G as getCreditCardFormInitialHeight, U as getCreditCardFormSrc, i as getEmbedOrigin, E as getGooglePayButtonInitialHeight, T as getGooglePayButtonSrc, re as mountAmosApplePayButton, te as mountAmosBankAccountPaymentMethodForm, ee as mountAmosCreditCardPaymentMethodForm, ne as mountAmosGooglePayButton, o as pickApplePayButtonElementProps, s as pickGooglePayButtonElementProps, _ as resetForm, b as sendConfirmationResult, u as sendParentReadyMessage, a as serializeWalletButtonStyle, m as updateAmount, d as updateAppearance, f as updateApplePayButton, p as updateGooglePayButton, h as updateMerchantName, g as validateForm };
|
package/dist/mount.d.ts
CHANGED
|
@@ -45,6 +45,9 @@ export type AmosPaymentMethodFormMountController = PaymentMethodFormController &
|
|
|
45
45
|
* element. Returns a controller exposing the underlying iframe, an
|
|
46
46
|
* `update()` method, and a `destroy()` method.
|
|
47
47
|
*
|
|
48
|
+
* A field-shaped skeleton is shown immediately and replaced by the
|
|
49
|
+
* iframe once appearance is applied.
|
|
50
|
+
*
|
|
48
51
|
* Use the returned `controller.iframe` when calling
|
|
49
52
|
* {@link validateForm}, {@link confirmPaymentIntent}, or
|
|
50
53
|
* {@link confirmSetupIntent}.
|
|
@@ -73,6 +76,9 @@ export type AmosBankAccountPaymentMethodFormOptions = PaymentMethodFormListenerO
|
|
|
73
76
|
* element. Returns a controller exposing the underlying iframe, an
|
|
74
77
|
* `update()` method, and a `destroy()` method.
|
|
75
78
|
*
|
|
79
|
+
* A field-shaped skeleton is shown immediately and replaced by the
|
|
80
|
+
* iframe once appearance is applied.
|
|
81
|
+
*
|
|
76
82
|
* Use the returned `controller.iframe` when calling
|
|
77
83
|
* {@link validateForm}, {@link confirmPaymentIntent}, or
|
|
78
84
|
* {@link confirmSetupIntent}.
|
package/dist/types.d.ts
CHANGED
|
@@ -106,6 +106,13 @@ export type ApplePayButtonType = "plain" | "buy" | "set-up" | "donate" | "check-
|
|
|
106
106
|
* @see https://developer.apple.com/documentation/apple_pay_on_the_web/apple-pay-button
|
|
107
107
|
*/
|
|
108
108
|
export type ApplePayButtonElementProps = {
|
|
109
|
+
/**
|
|
110
|
+
* Stretch the button to the iframe width while preserving its default
|
|
111
|
+
* compact size when omitted.
|
|
112
|
+
*
|
|
113
|
+
* @default false
|
|
114
|
+
*/
|
|
115
|
+
fullWidth?: boolean;
|
|
109
116
|
/**
|
|
110
117
|
* Apple Pay button color.
|
|
111
118
|
*
|
|
@@ -138,6 +145,13 @@ export type ApplePayButtonElementProps = {
|
|
|
138
145
|
* @see https://developers.google.com/pay/api/web/guides/resources/customize
|
|
139
146
|
*/
|
|
140
147
|
export type GooglePayButtonElementProps = {
|
|
148
|
+
/**
|
|
149
|
+
* Stretch the button to the iframe width while preserving its default
|
|
150
|
+
* compact size when omitted.
|
|
151
|
+
*
|
|
152
|
+
* @default false
|
|
153
|
+
*/
|
|
154
|
+
fullWidth?: boolean;
|
|
141
155
|
/**
|
|
142
156
|
* Button label / verb.
|
|
143
157
|
*
|
package/package.json
CHANGED
package/src/apple-pay.ts
CHANGED
|
@@ -209,6 +209,7 @@ export function attachApplePayButtonListeners(
|
|
|
209
209
|
const hadAmount = "amount" in patch;
|
|
210
210
|
const hadMerchantName = "merchantName" in patch;
|
|
211
211
|
const hadButtonProps =
|
|
212
|
+
"fullWidth" in patch ||
|
|
212
213
|
"buttonstyle" in patch ||
|
|
213
214
|
"type" in patch ||
|
|
214
215
|
"locale" in patch ||
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BillingAddressRequirement,
|
|
3
|
+
CreditCardAdditionalFields,
|
|
4
|
+
} from "./payment-method-form";
|
|
5
|
+
import type { Appearance, AppearanceLabels, ThemeVariable } from "./types";
|
|
6
|
+
|
|
7
|
+
const STYLE_ID = "amos-js-form-skeleton-styles";
|
|
8
|
+
|
|
9
|
+
const SKELETON_THEME_DEFAULTS: Record<string, string> = {
|
|
10
|
+
"--accent": "oklch(0.97 0 0)",
|
|
11
|
+
"--radius": "0.625rem",
|
|
12
|
+
"--input-height": "2.25rem",
|
|
13
|
+
"--floating-input-height": "3.25rem",
|
|
14
|
+
"--field-gap": "1rem",
|
|
15
|
+
"--control-gap": "0.5rem",
|
|
16
|
+
"--label-font-size": "0.875rem",
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const SKELETON_STYLES = `
|
|
20
|
+
.amos-js-form-skeleton {
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
container-type: inline-size;
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
gap: var(--field-gap);
|
|
26
|
+
margin: 0 -4px;
|
|
27
|
+
padding-block: 0.25rem;
|
|
28
|
+
pointer-events: none;
|
|
29
|
+
width: calc(100% + 8px);
|
|
30
|
+
}
|
|
31
|
+
.amos-js-form-skeleton-field {
|
|
32
|
+
display: flex;
|
|
33
|
+
flex: 1 1 0;
|
|
34
|
+
flex-direction: column;
|
|
35
|
+
min-width: 0;
|
|
36
|
+
width: 100%;
|
|
37
|
+
}
|
|
38
|
+
.amos-js-form-skeleton-label {
|
|
39
|
+
flex-shrink: 0;
|
|
40
|
+
font-size: var(--label-font-size);
|
|
41
|
+
height: 1.75rem;
|
|
42
|
+
line-height: 1.75rem;
|
|
43
|
+
}
|
|
44
|
+
.amos-js-form-skeleton-input {
|
|
45
|
+
animation: amos-js-skeleton-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
46
|
+
background: var(--accent);
|
|
47
|
+
border-radius: calc(var(--radius) * 0.8);
|
|
48
|
+
box-sizing: border-box;
|
|
49
|
+
height: var(--input-height);
|
|
50
|
+
width: 100%;
|
|
51
|
+
}
|
|
52
|
+
.amos-js-form-skeleton-input-floating {
|
|
53
|
+
height: var(--floating-input-height);
|
|
54
|
+
}
|
|
55
|
+
.amos-js-form-skeleton-row {
|
|
56
|
+
align-items: flex-start;
|
|
57
|
+
display: flex;
|
|
58
|
+
gap: var(--control-gap);
|
|
59
|
+
width: 100%;
|
|
60
|
+
}
|
|
61
|
+
.amos-js-form-skeleton-row-stack {
|
|
62
|
+
display: flex;
|
|
63
|
+
flex-direction: column;
|
|
64
|
+
gap: var(--field-gap);
|
|
65
|
+
width: 100%;
|
|
66
|
+
}
|
|
67
|
+
@container (min-width: 24rem) {
|
|
68
|
+
.amos-js-form-skeleton-row-stack {
|
|
69
|
+
align-items: flex-start;
|
|
70
|
+
flex-direction: row;
|
|
71
|
+
gap: var(--control-gap);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
@keyframes amos-js-skeleton-pulse {
|
|
75
|
+
50% { opacity: 0.5; }
|
|
76
|
+
}
|
|
77
|
+
@media (prefers-reduced-motion: reduce) {
|
|
78
|
+
.amos-js-form-skeleton-input {
|
|
79
|
+
animation: none;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
`;
|
|
83
|
+
|
|
84
|
+
function ensureSkeletonStyles(): void {
|
|
85
|
+
if (document.getElementById(STYLE_ID)) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const style = document.createElement("style");
|
|
89
|
+
style.id = STYLE_ID;
|
|
90
|
+
style.textContent = SKELETON_STYLES;
|
|
91
|
+
document.head.appendChild(style);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function applyTheme(
|
|
95
|
+
element: HTMLElement,
|
|
96
|
+
appearance: Appearance | undefined,
|
|
97
|
+
): void {
|
|
98
|
+
for (const [property, value] of Object.entries(SKELETON_THEME_DEFAULTS)) {
|
|
99
|
+
element.style.setProperty(property, value);
|
|
100
|
+
}
|
|
101
|
+
const themeVariables = appearance?.themeVariables;
|
|
102
|
+
if (!themeVariables) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
for (const [property, value] of Object.entries(themeVariables) as Array<
|
|
106
|
+
[ThemeVariable, string | undefined]
|
|
107
|
+
>) {
|
|
108
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
109
|
+
element.style.setProperty(property, value.trim());
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function div(className: string, children?: Array<HTMLElement>): HTMLDivElement {
|
|
115
|
+
const node = document.createElement("div");
|
|
116
|
+
node.className = className;
|
|
117
|
+
if (children) {
|
|
118
|
+
for (const child of children) {
|
|
119
|
+
node.appendChild(child);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return node;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function field(labels: AppearanceLabels, grow?: number): HTMLDivElement {
|
|
126
|
+
const wrap = div("amos-js-form-skeleton-field");
|
|
127
|
+
if (grow !== undefined) {
|
|
128
|
+
wrap.style.flexGrow = String(grow);
|
|
129
|
+
}
|
|
130
|
+
if (labels === "above") {
|
|
131
|
+
wrap.appendChild(div("amos-js-form-skeleton-label"));
|
|
132
|
+
}
|
|
133
|
+
const input = div("amos-js-form-skeleton-input");
|
|
134
|
+
if (labels === "floating") {
|
|
135
|
+
input.classList.add("amos-js-form-skeleton-input-floating");
|
|
136
|
+
}
|
|
137
|
+
wrap.appendChild(input);
|
|
138
|
+
return wrap;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function row(children: Array<HTMLElement>, wrapAtSm: boolean): HTMLDivElement {
|
|
142
|
+
return div(
|
|
143
|
+
wrapAtSm ? "amos-js-form-skeleton-row-stack" : "amos-js-form-skeleton-row",
|
|
144
|
+
children,
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function billingFields({
|
|
149
|
+
labels,
|
|
150
|
+
requirement,
|
|
151
|
+
wrapCountryZip,
|
|
152
|
+
}: {
|
|
153
|
+
labels: AppearanceLabels;
|
|
154
|
+
requirement: BillingAddressRequirement;
|
|
155
|
+
wrapCountryZip: boolean;
|
|
156
|
+
}): Array<HTMLElement> {
|
|
157
|
+
if (requirement === "full") {
|
|
158
|
+
return [
|
|
159
|
+
field(labels),
|
|
160
|
+
field(labels),
|
|
161
|
+
row([field(labels, 1.4), field(labels, 0.7), field(labels, 0.8)], false),
|
|
162
|
+
field(labels),
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
return [row([field(labels), field(labels)], wrapCountryZip)];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export type PaymentMethodFormSkeletonKind = "card" | "bank";
|
|
169
|
+
|
|
170
|
+
export type PaymentMethodFormSkeletonOptions = {
|
|
171
|
+
kind: PaymentMethodFormSkeletonKind;
|
|
172
|
+
appearance?: Appearance;
|
|
173
|
+
additionalFields?: CreditCardAdditionalFields;
|
|
174
|
+
billingAddressRequirement?: BillingAddressRequirement;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
function buildChildren(
|
|
178
|
+
options: PaymentMethodFormSkeletonOptions,
|
|
179
|
+
): Array<HTMLElement> {
|
|
180
|
+
const labels = options.appearance?.labels ?? "above";
|
|
181
|
+
const billingAddressRequirement =
|
|
182
|
+
options.billingAddressRequirement ?? "country";
|
|
183
|
+
|
|
184
|
+
if (options.kind === "card") {
|
|
185
|
+
const children: Array<HTMLElement> = [
|
|
186
|
+
field(labels),
|
|
187
|
+
row([field(labels), field(labels)], false),
|
|
188
|
+
];
|
|
189
|
+
if (options.additionalFields?.cardholderName) {
|
|
190
|
+
children.push(field(labels));
|
|
191
|
+
}
|
|
192
|
+
children.push(
|
|
193
|
+
...billingFields({
|
|
194
|
+
labels,
|
|
195
|
+
requirement: billingAddressRequirement,
|
|
196
|
+
wrapCountryZip: false,
|
|
197
|
+
}),
|
|
198
|
+
);
|
|
199
|
+
return children;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return [
|
|
203
|
+
field(labels),
|
|
204
|
+
row([field(labels), field(labels)], true),
|
|
205
|
+
field(labels),
|
|
206
|
+
row([field("above"), field("above")], true),
|
|
207
|
+
...billingFields({
|
|
208
|
+
labels,
|
|
209
|
+
requirement: billingAddressRequirement,
|
|
210
|
+
wrapCountryZip: true,
|
|
211
|
+
}),
|
|
212
|
+
];
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export type PaymentMethodFormSkeleton = {
|
|
216
|
+
element: HTMLElement;
|
|
217
|
+
update: (options: PaymentMethodFormSkeletonOptions) => void;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Host-page placeholder that mirrors card/bank field layout using the
|
|
222
|
+
* same appearance variables the iframe will apply. Shown immediately
|
|
223
|
+
* while the iframe document loads, then removed when appearance is
|
|
224
|
+
* ready.
|
|
225
|
+
*/
|
|
226
|
+
export function createPaymentMethodFormSkeleton(
|
|
227
|
+
options: PaymentMethodFormSkeletonOptions,
|
|
228
|
+
): PaymentMethodFormSkeleton {
|
|
229
|
+
ensureSkeletonStyles();
|
|
230
|
+
const element = div("amos-js-form-skeleton");
|
|
231
|
+
element.setAttribute("aria-hidden", "true");
|
|
232
|
+
|
|
233
|
+
function render(next: PaymentMethodFormSkeletonOptions): void {
|
|
234
|
+
applyTheme(element, next.appearance);
|
|
235
|
+
element.replaceChildren(...buildChildren(next));
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
render(options);
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
element,
|
|
242
|
+
update: render,
|
|
243
|
+
};
|
|
244
|
+
}
|
package/src/google-pay.ts
CHANGED
|
@@ -178,6 +178,7 @@ export function attachGooglePayButtonListeners(
|
|
|
178
178
|
const hadAmount = "amount" in patch;
|
|
179
179
|
const hadMerchantName = "merchantName" in patch;
|
|
180
180
|
const hadButtonProps =
|
|
181
|
+
"fullWidth" in patch ||
|
|
181
182
|
"buttonType" in patch ||
|
|
182
183
|
"buttonColor" in patch ||
|
|
183
184
|
"buttonRadius" in patch ||
|
package/src/mount.ts
CHANGED
|
@@ -5,6 +5,10 @@ import {
|
|
|
5
5
|
getApplePayButtonInitialHeight,
|
|
6
6
|
getApplePayButtonSrc,
|
|
7
7
|
} from "./apple-pay";
|
|
8
|
+
import {
|
|
9
|
+
createPaymentMethodFormSkeleton,
|
|
10
|
+
type PaymentMethodFormSkeletonOptions,
|
|
11
|
+
} from "./form-skeleton";
|
|
8
12
|
import {
|
|
9
13
|
attachGooglePayButtonListeners,
|
|
10
14
|
type GooglePayButtonController,
|
|
@@ -39,7 +43,7 @@ function resolveContainer(container: Container): HTMLElement {
|
|
|
39
43
|
return container;
|
|
40
44
|
}
|
|
41
45
|
|
|
42
|
-
const
|
|
46
|
+
const FORM_IFRAME_STYLE: Partial<CSSStyleDeclaration> = {
|
|
43
47
|
width: "calc(100% + 8px)",
|
|
44
48
|
transition: "opacity 150ms ease-in, height 200ms ease-in-out",
|
|
45
49
|
margin: "0 -4px",
|
|
@@ -47,18 +51,40 @@ const SHARED_IFRAME_STYLE: Partial<CSSStyleDeclaration> = {
|
|
|
47
51
|
border: "0",
|
|
48
52
|
};
|
|
49
53
|
|
|
54
|
+
const WALLET_IFRAME_STYLE: Partial<CSSStyleDeclaration> = {
|
|
55
|
+
width: "100%",
|
|
56
|
+
transition: "height 200ms ease-in-out",
|
|
57
|
+
margin: "0",
|
|
58
|
+
opacity: "0",
|
|
59
|
+
border: "0",
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const SKELETON_IFRAME_STYLE: Partial<CSSStyleDeclaration> = {
|
|
63
|
+
position: "absolute",
|
|
64
|
+
top: "0",
|
|
65
|
+
left: "-4px",
|
|
66
|
+
width: "calc(100% + 8px)",
|
|
67
|
+
height: "100%",
|
|
68
|
+
margin: "0",
|
|
69
|
+
// Do not interpolate opacity while the skeleton is showing.
|
|
70
|
+
transition: "none",
|
|
71
|
+
pointerEvents: "none",
|
|
72
|
+
};
|
|
73
|
+
|
|
50
74
|
function createIframe({
|
|
51
75
|
src,
|
|
52
76
|
title,
|
|
53
77
|
name,
|
|
54
78
|
height,
|
|
55
79
|
allow,
|
|
80
|
+
style = FORM_IFRAME_STYLE,
|
|
56
81
|
}: {
|
|
57
82
|
src: string;
|
|
58
83
|
title: string;
|
|
59
84
|
name: string;
|
|
60
85
|
height: string;
|
|
61
86
|
allow?: string;
|
|
87
|
+
style?: Partial<CSSStyleDeclaration>;
|
|
62
88
|
}): HTMLIFrameElement {
|
|
63
89
|
const iframe = document.createElement("iframe");
|
|
64
90
|
iframe.src = src;
|
|
@@ -69,10 +95,137 @@ function createIframe({
|
|
|
69
95
|
if (allow) {
|
|
70
96
|
iframe.allow = allow;
|
|
71
97
|
}
|
|
72
|
-
Object.assign(iframe.style,
|
|
98
|
+
Object.assign(iframe.style, style, { height });
|
|
73
99
|
return iframe;
|
|
74
100
|
}
|
|
75
101
|
|
|
102
|
+
function mountPaymentMethodFormWithSkeleton({
|
|
103
|
+
host,
|
|
104
|
+
iframe,
|
|
105
|
+
listenerOptions,
|
|
106
|
+
skeletonOptions,
|
|
107
|
+
}: {
|
|
108
|
+
host: HTMLElement;
|
|
109
|
+
iframe: HTMLIFrameElement;
|
|
110
|
+
listenerOptions: PaymentMethodFormListenerOptions;
|
|
111
|
+
skeletonOptions: PaymentMethodFormSkeletonOptions;
|
|
112
|
+
}): AmosPaymentMethodFormMountController {
|
|
113
|
+
const wrapper = document.createElement("div");
|
|
114
|
+
wrapper.style.position = "relative";
|
|
115
|
+
wrapper.style.width = "100%";
|
|
116
|
+
wrapper.setAttribute("aria-busy", "true");
|
|
117
|
+
|
|
118
|
+
const skeleton = createPaymentMethodFormSkeleton(skeletonOptions);
|
|
119
|
+
Object.assign(iframe.style, SKELETON_IFRAME_STYLE);
|
|
120
|
+
|
|
121
|
+
wrapper.append(skeleton.element, iframe);
|
|
122
|
+
host.appendChild(wrapper);
|
|
123
|
+
|
|
124
|
+
let revealed = false;
|
|
125
|
+
let appearanceReady = false;
|
|
126
|
+
let lastHeight: string | undefined;
|
|
127
|
+
let appearance = skeletonOptions.appearance;
|
|
128
|
+
let heightTransitionTimer: ReturnType<typeof setTimeout> | undefined;
|
|
129
|
+
let fallbackRevealTimer: ReturnType<typeof setTimeout> | undefined;
|
|
130
|
+
|
|
131
|
+
function skeletonHeightPx(): number {
|
|
132
|
+
return wrapper.getBoundingClientRect().height;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function reportedHeightPx(): number {
|
|
136
|
+
return lastHeight ? Number.parseFloat(lastHeight) : Number.NaN;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function reveal(): void {
|
|
140
|
+
if (revealed) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
revealed = true;
|
|
144
|
+
if (fallbackRevealTimer !== undefined) {
|
|
145
|
+
clearTimeout(fallbackRevealTimer);
|
|
146
|
+
fallbackRevealTimer = undefined;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const skeletonPx = skeletonHeightPx();
|
|
150
|
+
const reportedPx = reportedHeightPx();
|
|
151
|
+
const revealPx = Number.isFinite(reportedPx)
|
|
152
|
+
? Math.max(reportedPx, skeletonPx)
|
|
153
|
+
: skeletonPx;
|
|
154
|
+
|
|
155
|
+
iframe.style.transition = "none";
|
|
156
|
+
iframe.style.position = "";
|
|
157
|
+
iframe.style.top = "";
|
|
158
|
+
iframe.style.left = "";
|
|
159
|
+
iframe.style.margin = FORM_IFRAME_STYLE.margin ?? "";
|
|
160
|
+
iframe.style.height = `${revealPx}px`;
|
|
161
|
+
iframe.style.opacity = "1";
|
|
162
|
+
iframe.style.pointerEvents = "";
|
|
163
|
+
skeleton.element.remove();
|
|
164
|
+
wrapper.removeAttribute("aria-busy");
|
|
165
|
+
|
|
166
|
+
// Height easing is for later layout changes (ZIP show/hide, errors),
|
|
167
|
+
// not the first paint — that would animate the last row into place.
|
|
168
|
+
heightTransitionTimer = setTimeout(() => {
|
|
169
|
+
iframe.style.transition = "height 200ms ease-in-out";
|
|
170
|
+
}, 400);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function tryReveal(): void {
|
|
174
|
+
if (revealed || !appearanceReady) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const reportedPx = reportedHeightPx();
|
|
178
|
+
const skeletonPx = skeletonHeightPx();
|
|
179
|
+
if (Number.isFinite(reportedPx) && reportedPx >= skeletonPx - 2) {
|
|
180
|
+
reveal();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const controller = attachPaymentMethodFormListeners(iframe, {
|
|
185
|
+
...listenerOptions,
|
|
186
|
+
onHeightChange: (height) => {
|
|
187
|
+
lastHeight = height;
|
|
188
|
+
if (revealed) {
|
|
189
|
+
iframe.style.height = height;
|
|
190
|
+
} else {
|
|
191
|
+
tryReveal();
|
|
192
|
+
}
|
|
193
|
+
listenerOptions.onHeightChange?.(height);
|
|
194
|
+
},
|
|
195
|
+
onAppearanceReady: () => {
|
|
196
|
+
appearanceReady = true;
|
|
197
|
+
tryReveal();
|
|
198
|
+
if (!revealed && fallbackRevealTimer === undefined) {
|
|
199
|
+
fallbackRevealTimer = setTimeout(() => {
|
|
200
|
+
reveal();
|
|
201
|
+
}, 1500);
|
|
202
|
+
}
|
|
203
|
+
listenerOptions.onAppearanceReady?.();
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
iframe,
|
|
209
|
+
update(patch) {
|
|
210
|
+
controller.update(patch);
|
|
211
|
+
if (!revealed && "appearance" in patch) {
|
|
212
|
+
appearance = patch.appearance;
|
|
213
|
+
skeleton.update({ ...skeletonOptions, appearance });
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
destroy() {
|
|
217
|
+
if (heightTransitionTimer !== undefined) {
|
|
218
|
+
clearTimeout(heightTransitionTimer);
|
|
219
|
+
}
|
|
220
|
+
if (fallbackRevealTimer !== undefined) {
|
|
221
|
+
clearTimeout(fallbackRevealTimer);
|
|
222
|
+
}
|
|
223
|
+
controller.destroy();
|
|
224
|
+
wrapper.remove();
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
76
229
|
/**
|
|
77
230
|
* Options accepted by {@link mountAmosCreditCardPaymentMethodForm}.
|
|
78
231
|
*/
|
|
@@ -120,6 +273,9 @@ export type AmosPaymentMethodFormMountController =
|
|
|
120
273
|
* element. Returns a controller exposing the underlying iframe, an
|
|
121
274
|
* `update()` method, and a `destroy()` method.
|
|
122
275
|
*
|
|
276
|
+
* A field-shaped skeleton is shown immediately and replaced by the
|
|
277
|
+
* iframe once appearance is applied.
|
|
278
|
+
*
|
|
123
279
|
* Use the returned `controller.iframe` when calling
|
|
124
280
|
* {@link validateForm}, {@link confirmPaymentIntent}, or
|
|
125
281
|
* {@link confirmSetupIntent}.
|
|
@@ -149,28 +305,18 @@ export function mountAmosCreditCardPaymentMethodForm(
|
|
|
149
305
|
billingAddressRequirement,
|
|
150
306
|
),
|
|
151
307
|
});
|
|
152
|
-
host.appendChild(iframe);
|
|
153
308
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
onHeightChange: (height) => {
|
|
157
|
-
iframe.style.height = height;
|
|
158
|
-
listenerOptions.onHeightChange?.(height);
|
|
159
|
-
},
|
|
160
|
-
onAppearanceReady: () => {
|
|
161
|
-
iframe.style.opacity = "1";
|
|
162
|
-
listenerOptions.onAppearanceReady?.();
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
return {
|
|
309
|
+
return mountPaymentMethodFormWithSkeleton({
|
|
310
|
+
host,
|
|
167
311
|
iframe,
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
312
|
+
listenerOptions,
|
|
313
|
+
skeletonOptions: {
|
|
314
|
+
kind: "card",
|
|
315
|
+
appearance: listenerOptions.appearance,
|
|
316
|
+
additionalFields,
|
|
317
|
+
billingAddressRequirement,
|
|
172
318
|
},
|
|
173
|
-
};
|
|
319
|
+
});
|
|
174
320
|
}
|
|
175
321
|
|
|
176
322
|
/**
|
|
@@ -198,6 +344,9 @@ export type AmosBankAccountPaymentMethodFormOptions =
|
|
|
198
344
|
* element. Returns a controller exposing the underlying iframe, an
|
|
199
345
|
* `update()` method, and a `destroy()` method.
|
|
200
346
|
*
|
|
347
|
+
* A field-shaped skeleton is shown immediately and replaced by the
|
|
348
|
+
* iframe once appearance is applied.
|
|
349
|
+
*
|
|
201
350
|
* Use the returned `controller.iframe` when calling
|
|
202
351
|
* {@link validateForm}, {@link confirmPaymentIntent}, or
|
|
203
352
|
* {@link confirmSetupIntent}.
|
|
@@ -219,28 +368,17 @@ export function mountAmosBankAccountPaymentMethodForm(
|
|
|
219
368
|
name: "amos-bank-account-payment-method-form",
|
|
220
369
|
height: getBankAccountFormInitialHeight(billingAddressRequirement),
|
|
221
370
|
});
|
|
222
|
-
host.appendChild(iframe);
|
|
223
371
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
onHeightChange: (height) => {
|
|
227
|
-
iframe.style.height = height;
|
|
228
|
-
listenerOptions.onHeightChange?.(height);
|
|
229
|
-
},
|
|
230
|
-
onAppearanceReady: () => {
|
|
231
|
-
iframe.style.opacity = "1";
|
|
232
|
-
listenerOptions.onAppearanceReady?.();
|
|
233
|
-
},
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
return {
|
|
372
|
+
return mountPaymentMethodFormWithSkeleton({
|
|
373
|
+
host,
|
|
237
374
|
iframe,
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
375
|
+
listenerOptions,
|
|
376
|
+
skeletonOptions: {
|
|
377
|
+
kind: "bank",
|
|
378
|
+
appearance: listenerOptions.appearance,
|
|
379
|
+
billingAddressRequirement,
|
|
242
380
|
},
|
|
243
|
-
};
|
|
381
|
+
});
|
|
244
382
|
}
|
|
245
383
|
|
|
246
384
|
/**
|
|
@@ -284,6 +422,7 @@ export function mountAmosGooglePayButton(
|
|
|
284
422
|
name: "amos-google-pay-button",
|
|
285
423
|
height: getGooglePayButtonInitialHeight(),
|
|
286
424
|
allow: "payment",
|
|
425
|
+
style: WALLET_IFRAME_STYLE,
|
|
287
426
|
});
|
|
288
427
|
host.appendChild(iframe);
|
|
289
428
|
|
|
@@ -350,6 +489,7 @@ export function mountAmosApplePayButton(
|
|
|
350
489
|
name: "amos-apple-pay-button",
|
|
351
490
|
height: getApplePayButtonInitialHeight(),
|
|
352
491
|
allow: "payment",
|
|
492
|
+
style: WALLET_IFRAME_STYLE,
|
|
353
493
|
});
|
|
354
494
|
host.appendChild(iframe);
|
|
355
495
|
|
package/src/types.ts
CHANGED
|
@@ -361,6 +361,13 @@ export type ApplePayButtonType =
|
|
|
361
361
|
* @see https://developer.apple.com/documentation/apple_pay_on_the_web/apple-pay-button
|
|
362
362
|
*/
|
|
363
363
|
export type ApplePayButtonElementProps = {
|
|
364
|
+
/**
|
|
365
|
+
* Stretch the button to the iframe width while preserving its default
|
|
366
|
+
* compact size when omitted.
|
|
367
|
+
*
|
|
368
|
+
* @default false
|
|
369
|
+
*/
|
|
370
|
+
fullWidth?: boolean;
|
|
364
371
|
/**
|
|
365
372
|
* Apple Pay button color.
|
|
366
373
|
*
|
|
@@ -394,6 +401,13 @@ export type ApplePayButtonElementProps = {
|
|
|
394
401
|
* @see https://developers.google.com/pay/api/web/guides/resources/customize
|
|
395
402
|
*/
|
|
396
403
|
export type GooglePayButtonElementProps = {
|
|
404
|
+
/**
|
|
405
|
+
* Stretch the button to the iframe width while preserving its default
|
|
406
|
+
* compact size when omitted.
|
|
407
|
+
*
|
|
408
|
+
* @default false
|
|
409
|
+
*/
|
|
410
|
+
fullWidth?: boolean;
|
|
397
411
|
/**
|
|
398
412
|
* Button label / verb.
|
|
399
413
|
*
|
|
@@ -452,6 +466,9 @@ export function pickApplePayButtonElementProps(
|
|
|
452
466
|
options: ApplePayButtonElementProps,
|
|
453
467
|
): ApplePayButtonElementProps {
|
|
454
468
|
const props: ApplePayButtonElementProps = {};
|
|
469
|
+
if (options.fullWidth !== undefined) {
|
|
470
|
+
props.fullWidth = options.fullWidth;
|
|
471
|
+
}
|
|
455
472
|
if (options.buttonstyle !== undefined) {
|
|
456
473
|
props.buttonstyle = options.buttonstyle;
|
|
457
474
|
}
|
|
@@ -474,6 +491,9 @@ export function pickGooglePayButtonElementProps(
|
|
|
474
491
|
options: GooglePayButtonElementProps,
|
|
475
492
|
): GooglePayButtonElementProps {
|
|
476
493
|
const props: GooglePayButtonElementProps = {};
|
|
494
|
+
if (options.fullWidth !== undefined) {
|
|
495
|
+
props.fullWidth = options.fullWidth;
|
|
496
|
+
}
|
|
477
497
|
if (options.buttonType !== undefined) {
|
|
478
498
|
props.buttonType = options.buttonType;
|
|
479
499
|
}
|