@liquidcommerce/elements-sdk 2.6.0-beta.119 → 2.6.0-beta.120

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.
Files changed (40) hide show
  1. package/README.md +1 -0
  2. package/dist/index.checkout.esm.js +9187 -8014
  3. package/dist/index.esm.js +14030 -12873
  4. package/dist/ssr-stub.esm.js +3 -0
  5. package/dist/types/clients/base.d.ts +1 -0
  6. package/dist/types/clients/helpers.d.ts +2 -1
  7. package/dist/types/core/api/api-client.service.d.ts +6 -3
  8. package/dist/types/core/pubsub/interfaces/checkout.interface.d.ts +5 -0
  9. package/dist/types/core/pubsub/interfaces/core.interface.d.ts +2 -1
  10. package/dist/types/core/store/interfaces/checkout.interface.d.ts +9 -0
  11. package/dist/types/core/store/interfaces/core.interface.d.ts +2 -2
  12. package/dist/types/enums/core.enum.d.ts +3 -0
  13. package/dist/types/index.checkout.d.ts +2 -1
  14. package/dist/types/interfaces/api/checkout.interface.d.ts +7 -0
  15. package/dist/types/interfaces/client.interface.d.ts +3 -1
  16. package/dist/types/interfaces/configs/checkout.interface.d.ts +1 -0
  17. package/dist/types/interfaces/injection.interface.d.ts +6 -0
  18. package/dist/types/modules/checkout/checkout.commands.d.ts +27 -3
  19. package/dist/types/modules/checkout/components/checkout-buyer.component.d.ts +1 -0
  20. package/dist/types/modules/checkout/components/checkout-deliver-to.component.d.ts +1 -0
  21. package/dist/types/modules/checkout/components/checkout-express-checkout.component.d.ts +61 -0
  22. package/dist/types/modules/checkout/components/checkout-express-completion.component.d.ts +21 -0
  23. package/dist/types/modules/checkout/components/index.d.ts +2 -0
  24. package/dist/types/modules/checkout/constant.d.ts +2 -0
  25. package/dist/types/modules/checkout/customer-prefill.d.ts +4 -1
  26. package/dist/types/modules/checkout/express-wallet.d.ts +12 -0
  27. package/dist/types/modules/checkout/styles/express-checkout.style.d.ts +1 -0
  28. package/dist/types/modules/checkout/styles/express-completion.style.d.ts +1 -0
  29. package/dist/types/modules/ui-components/input/input.component.d.ts +1 -1
  30. package/dist/types/utils/format.d.ts +4 -0
  31. package/docs/v1/api/actions/checkout-actions.md +3 -1
  32. package/docs/v1/api/client.md +49 -0
  33. package/docs/v1/api/configuration.md +3 -1
  34. package/docs/v1/api/typescript-types.md +10 -1
  35. package/docs/v1/guides/accessibility.md +21 -0
  36. package/docs/v1/guides/checkout-component.md +66 -3
  37. package/docs/v1/guides/events.md +19 -0
  38. package/docs/v1/guides/theming.md +1 -0
  39. package/docs/v1/reference/analytics.md +14 -2
  40. package/package.json +1 -1
@@ -105,6 +105,7 @@ Content that appears or changes without navigation is announced through a shared
105
105
  | Cart or checkout opened / closed | "Shopping cart opened" / "Shopping cart closed" |
106
106
  | Panel closed (product) | "Closed. Back to product options." |
107
107
  | Item added / removed, promo applied, totals changed | The new state, e.g. "Promo code SPRING applied, $5.00 off" |
108
+ | Express checkout payment failed | "Express checkout failed. …" |
108
109
  | Product list filtered or searched | "12 products found, showing 12" |
109
110
  | Validation failed | The field name and the error, interrupting (assertive) |
110
111
  | Carousel image changed | "Image 2 of 4" |
@@ -163,6 +164,26 @@ element on a page labels its own sections.
163
164
  The checkout element has its own outline and is not covered by the above. Where any element's
164
165
  top-level heading sits in **your** page's outline is yours to place.
165
166
 
167
+ ### Express checkout
168
+
169
+ The Apple Pay and Google Pay buttons are rendered by Stripe inside an iframe, so their own labels
170
+ and keyboard behaviour are Stripe's. What the SDK owns around them:
171
+
172
+ - The **"Express Checkout" heading** is an `h3`, matching the other checkout section headings. It is
173
+ rendered only by the `section` variant; injected on their own the buttons carry no heading, and the
174
+ host page's own outline supplies it.
175
+ - The **`OR` divider** is decorative and carries `aria-hidden="true"`, so "OR" is not announced as
176
+ content between the buttons and the section below.
177
+ - When the shopper's device offers **no wallet**, the heading and the divider are removed from the
178
+ accessibility tree along with the buttons, so no orphan rule or empty heading is left behind. The block is also removed on a gift order, which express cannot place, and where a
179
+ payment method is already bound to the checkout. It is offered to every shopper otherwise.
180
+ - The **wallet sheet is browser UI**, not an SDK overlay: the browser owns focus while it is open and
181
+ returns it to the button that opened it. Dismissing the sheet changes nothing in the page, so
182
+ nothing is announced.
183
+ - Failures are announced assertively, because the shopper has just authorised a payment and the sheet
184
+ that showed the error has already closed. Confirming the sheet places the order outright, so there
185
+ is nothing to announce on the success path beyond the order confirmation itself.
186
+
166
187
  ### Images and icons
167
188
 
168
189
  - Product photos use the product name as their alt text; a photo painted as a CSS background is
@@ -402,6 +402,16 @@ window.addEventListener('lce:actions.checkout_submit_failed', (event) => {
402
402
  });
403
403
  ```
404
404
 
405
+ ### Express Checkout
406
+
407
+ ```javascript
408
+ // Wallet availability settled or changed (always fires at least once per block)
409
+ window.addEventListener('lce:actions.checkout_express_checkout_availability', (event) => {
410
+ const { data } = event.detail;
411
+ console.log(data.available ? `Wallets: ${data.wallets.join(', ')}` : 'No wallets available');
412
+ });
413
+ ```
414
+
405
415
  ### Promo Codes
406
416
 
407
417
  ```javascript
@@ -496,13 +506,63 @@ const client = await Elements('YOUR_API_KEY', {
496
506
 
497
507
  The SDK uses Stripe for payment processing. Payment form is embedded and handles:
498
508
  - Credit/debit cards
499
- - Apple Pay (when available)
500
- - Google Pay (when available)
501
509
  - PCI compliance
502
510
  - 3D Secure authentication
503
511
 
504
512
  No additional Stripe integration code needed - it's built-in.
505
513
 
514
+ ### Express checkout (Apple Pay and Google Pay)
515
+
516
+ Apple Pay and Google Pay are offered as express checkout buttons at the top of the checkout, above
517
+ the gift toggle. Tapping one collects the shopper's contact and billing details from the wallet and
518
+ places the order without them completing the checkout forms.
519
+
520
+ Express checkout is offered to every shopper whose platform can show a wallet. Each wallet is
521
+ requested with Stripe's `always` policy, so the button renders wherever the device supports it rather
522
+ than only where Stripe judges it good for conversion. The block hides itself entirely — heading,
523
+ buttons and divider — in four cases: the device or browser offers no wallet, the order is a
524
+ gift, a payment method is already bound to the checkout, or Stripe.js fails to load. Subscribe to
525
+ [`lce:actions.checkout_express_checkout_availability`](./events.md) to know which state you are in.
526
+
527
+ Two things are required outside the SDK:
528
+
529
+ - **The page must be served over HTTPS.** Stripe requires this in development as well as production;
530
+ the wallet buttons do not render on a plain-HTTP page.
531
+ - **Every domain that serves the buttons must be registered with Stripe** for the account issuing the
532
+ publishable key, in both sandbox and live mode. Stripe requires this for Apple Pay and Google Pay
533
+ alike, and it covers subdomains: `shop.example.com` is registered separately from `example.com`.
534
+ Registering in live mode registers the sandbox too. This applies per partner domain.
535
+
536
+ Approving the wallet sheet hands the order to the **express completion view**, which replaces the
537
+ checkout form the moment the sheet closes. The view saves the shopper's name, email and phone from
538
+ the wallet as the checkout's customer and binds the approved payment method; the wallet's billing
539
+ address goes to Stripe with that payment method, and the order's own billing address stays the one
540
+ the checkout already holds. Then it asks for the one thing no wallet returns — the shopper's **date
541
+ of birth** — with the same 21+ validation as the form, and places the order from its **Complete
542
+ order** button. A date the shopper already typed into the form is used instead, and the view goes
543
+ straight to placing the order. When the partner has turned off **Require date of birth** in the
544
+ builder (`checkout.layout.requireBirthDate: false`), the view skips the step and places the order as
545
+ soon as the payment method is bound. A shopper can step **back to checkout** from the view; the
546
+ payment method stays bound, and the form asks for the date of birth itself when one is required.
547
+
548
+ If the wallet sheet itself fails — a declined authorisation, or a total that changed while it was
549
+ open — the sheet reports the reason and nothing is handed on. Anything that fails after the sheet
550
+ has closed is reported on the view, with a retry. The order is placed only for the checkout and the
551
+ total the sheet was opened for: the server verifies both against the wallet's intent at completion,
552
+ so a total that moved in between is refused there as well and the shopper approves again.
553
+
554
+ The wallet tap is also refused, with nothing charged, when a cart is below a retailer's minimum
555
+ purchase amount — the same condition that keeps the Place Order button disabled. Presale checkouts
556
+ are exempt from it, as they are there.
557
+
558
+ Express checkout is not offered on a gift order: a gift needs the recipient's name, email, phone and
559
+ message, and no wallet returns any of them. Turning on "Send as a gift" hides the block, and turning
560
+ it back off restores it.
561
+
562
+ The buttons are not confined to the checkout element. Inject them anywhere on the page with
563
+ `injectExpressCheckoutElement()` on the full client, or `injectExpressCheckout()` on the
564
+ checkout-only client.
565
+
506
566
  ## Checkout Flow
507
567
 
508
568
  ### Standard Flow
@@ -623,6 +683,7 @@ window.addEventListener('lce:actions.checkout_submit_failed', () => {
623
683
  checkout: {
624
684
  layout: {
625
685
  allowGiftCards: true, // Show gift card input
686
+ requireBirthDate: true, // Require a date of birth to place an order
626
687
  emailOptIn: {
627
688
  show: true, // Show email opt-in checkbox
628
689
  checked: false, // Default unchecked
@@ -691,7 +752,9 @@ After `lce:actions.checkout_loaded`, call
691
752
  `await elements.actions.checkout.updateCustomerInfo(fields, { saveIfValid: true })`
692
753
  to validate and prepare complete account details, then show their editable summary.
693
754
  Supply names, email, a US phone number, and a real `birthDate` in `MM/DD/YYYY` format
694
- (age 21+, year 1930 or later). A shipping street must already be selected.
755
+ (age 21+, year 1930 or later). The `birthDate` may be blank when the partner does not require a
756
+ date of birth (`checkout.layout.requireBirthDate: false`); a supplied one is still validated.
757
+ A shipping street must already be selected.
695
758
  Omitted apartment and delivery instructions retain their existing checkout values.
696
759
  Partial or invalid details stay in the form; backend validation failures reject the
697
760
  promise, show the checkout error, and keep details editable. The host should handle that rejection.
@@ -858,6 +858,25 @@ window.addEventListener('lce:actions.checkout_gift_card_failed', (event) => {
858
858
  });
859
859
  ```
860
860
 
861
+ ### `lce:actions.checkout_express_checkout_availability`
862
+
863
+ Fires once the express checkout block has settled which wallet buttons the shopper can reach, and
864
+ again whenever that changes. It always fires at least once per block. `available` is `false` on a
865
+ device or browser that offers no wallet, on a gift order, when a payment method is already bound to
866
+ the checkout, and when Stripe.js cannot load; in every case the SDK hides the whole block including
867
+ its divider.
868
+
869
+ **Data includes:** `cartId`, `available`, `wallets`.
870
+
871
+ **Example**
872
+
873
+ ```javascript
874
+ window.addEventListener('lce:actions.checkout_express_checkout_availability', (event) => {
875
+ const { data } = event.detail;
876
+ console.log(data.available ? `Wallets: ${data.wallets.join(', ')}` : 'No wallets available');
877
+ });
878
+ ```
879
+
861
880
  ### `lce:actions.checkout_product_add_success`
862
881
 
863
882
  Fires when products are added to checkout via the actions API.
@@ -168,6 +168,7 @@ customTheme: {
168
168
  text: 'Receive SMS updates about your order and exclusive deals.'
169
169
  },
170
170
  allowGiftCards: true,
171
+ requireBirthDate: true,
171
172
  legalMessage: { show: true, text: 'By placing your order, you agree to our Terms of Service and Privacy Policy.' },
172
173
  continueShoppingUrl: 'https://yoursite.com/shop',
173
174
  exitUrl: 'https://yoursite.com',
@@ -52,7 +52,17 @@ The SDK detects an already-present partner/host GTM container rather than replac
52
52
 
53
53
  ### Google tag gateway
54
54
 
55
- If your site loads its own GTM container first-party through [Google tag gateway for advertisers](https://developers.google.com/tag-platform/tag-manager/gateway/get-started) (e.g. `https://www.yoursite.com/metrics/` instead of `https://www.googletagmanager.com/gtm.js?id=GTM-XXXX`), tell the SDK where that path is so it recognizes your container:
55
+ [Google tag gateway for advertisers](https://developers.google.com/tag-platform/tag-manager/gateway/get-started) serves your Google tags from your own domain instead of Google's. Your GTM container loads from a first-party path such as `https://www.yoursite.com/metrics/` instead of `https://www.googletagmanager.com/gtm.js?id=GTM-XXXX`, and its measurement requests (e.g. GA4 `/g/collect` hits) go out through that same path. Your CDN or load balancer forwards them to Google, so they are less likely to be blocked than requests to Google's domains.
56
+
57
+ #### How the SDK works with it
58
+
59
+ - The SDK pushes every event to the page's `window.dataLayer`. Your container reads that same `dataLayer`, so it receives SDK events whether it loads from Google or from your gateway. Keep the default `dataLayer` name: a container renamed with `&l=` never sees them.
60
+ - The SDK never loads your container and proxies nothing. The LiquidCommerce container still loads from `googletagmanager.com`.
61
+ - To send SDK events to your own GA4 property, add a Custom Event trigger in your container on the [event names](#events) below and a GA4 Event tag that fires on it. The SDK puts `items`, `value` and `currency` at the top level of each event, not inside an `ecommerce` object, so map them with Data Layer Variables rather than the GA4 tag's "Send Ecommerce data" option.
62
+
63
+ #### `gatewayUrl`
64
+
65
+ Tell the SDK your gateway path so it can recognize your container:
56
66
 
57
67
  ```javascript
58
68
  const client = await Elements('YOUR_API_KEY', {
@@ -62,7 +72,9 @@ const client = await Elements('YOUR_API_KEY', {
62
72
 
63
73
  Or declaratively, on the script tag: `data-gtm-gateway-url="/metrics/"`.
64
74
 
65
- A gateway script URL usually carries no container ID, so without this setting the SDK cannot match the script tag to your partner container. A script with the same origin whose path starts with that value is matched to your partner container by container ID: an `id=` query parameter must equal your partner container ID, and a script without one counts only once GTM's `window.google_tag_manager` registry lists your container ID (or while no container has booted yet). A gateway serving a different container or a GA4/Ads tag is therefore never taken for yours. Relative values resolve against the current page. The setting affects detection only — the SDK never loads your container, and the LiquidCommerce container still loads from `googletagmanager.com`.
75
+ A gateway script URL usually carries no container ID, so until GTM has booted your container this setting is the only way the SDK can match the script tag to it. Once matched, your container ID is added to each event's `send_to` targets. The setting is optional: events reach your container through `dataLayer` without it.
76
+
77
+ A script with the same origin whose path starts with that value is matched to your partner container by container ID: an `id=` query parameter must equal your partner container ID, and a script without one counts only once GTM's `window.google_tag_manager` registry lists your container ID (or while no container has booted yet). A gateway serving a different container or a GA4/Ads tag is therefore never taken for yours. Relative values resolve against the current page.
66
78
 
67
79
  When both the LiquidCommerce container and a partner container are initialized, events are sent to both using GA4's `send_to` targeting (a dual-container send). Only containers that are actually initialized are added to `send_to`, so events are never routed to a container that failed to load.
68
80
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "LiquidCommerce Elements SDK",
4
4
  "license": "UNLICENSED",
5
5
  "author": "LiquidCommerce Team",
6
- "version": "2.6.0-beta.119",
6
+ "version": "2.6.0-beta.120",
7
7
  "homepage": "https://docs.liquidcommerce.co/elements-sdk",
8
8
  "repository": {
9
9
  "type": "git",