@liquidcommerce/elements-sdk 2.7.42 → 2.7.43

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.
@@ -142,6 +142,7 @@ const ELEMENTS_ACTIONS_EVENT = {
142
142
  CHECKOUT_PRODUCT_ADD_SUCCESS: 'checkout_product_add_success',
143
143
  CHECKOUT_PRODUCT_ADD_FAILED: 'checkout_product_add_failed',
144
144
  CHECKOUT_EXPRESS_CHECKOUT_AVAILABILITY: 'checkout_express_checkout_availability',
145
+ CHECKOUT_PAYMENT_FORM_FAILED: 'checkout_payment_form_failed',
145
146
  };
146
147
  const ELEMENTS_FORM = {
147
148
  CUSTOMER: 'customer',
@@ -15,8 +15,8 @@ export declare class ApiClientService {
15
15
  setPersistedStore(userDeviceId: string, data: IPersistedStore): Promise<ApiResult<IPersistedStoreAction>>;
16
16
  getPersistedStore(userDeviceId: string): Promise<ApiResult<IPersistedStore>>;
17
17
  deletePersistedStore(userDeviceId: string): Promise<ApiResult<IPersistedStoreAction>>;
18
- getAddressSuggestions(input: string): Promise<ApiResult<IAddressAutocompleteResult[]>>;
19
- getAddressDetails(id: string): Promise<ApiResult<IAddressDetailsResult>>;
18
+ getAddressSuggestions(input: string, sessionToken?: string): Promise<ApiResult<IAddressAutocompleteResult[]>>;
19
+ getAddressDetails(id: string, sessionToken?: string): Promise<ApiResult<IAddressDetailsResult>>;
20
20
  getProductsData(identifier: string[], location?: ILocation): Promise<ApiResult<IProductAvailabilityResponse>>;
21
21
  productListSearch(params: IProductSearchParams): Promise<ApiResult<IProductSearchResponse>>;
22
22
  getProductAvailabilityByState(identifiers: string[], state?: string): Promise<ApiResult<IProductAvailabilityResponse>>;
@@ -1,7 +1,7 @@
1
1
  import type { IAddressAddress, IAddressCoordinates, IAddressData } from '@/interfaces/api/address.interface';
2
2
  import { BaseActionService } from './base-action.service';
3
3
  export interface IAddressActions {
4
- setAddressByPlacesId: (placesId: string) => Promise<void>;
4
+ setAddressByPlacesId: (placesId: string, sessionToken?: string) => Promise<void>;
5
5
  setAddressManually: (address: IAddressAddress, coordinates: IAddressCoordinates) => Promise<void>;
6
6
  clear: () => Promise<void>;
7
7
  getDetails: () => IAddressData | null;
@@ -118,3 +118,7 @@ export interface ICheckoutExpressCheckoutAvailabilityEventData {
118
118
  available: boolean;
119
119
  wallets: string[];
120
120
  }
121
+ export interface ICheckoutPaymentFormFailedEventData {
122
+ cartId: string;
123
+ reason: 'blocked' | 'timeout' | 'error';
124
+ }
@@ -1,6 +1,6 @@
1
1
  import type { IAddressActionEventData, IAddressFailedEventData } from '@/core/pubsub/interfaces/address.interface';
2
2
  import type { ICartFailedEventData, ICartItemAddedEventData, ICartItemEngravingUpdatedEventData, ICartItemQuantityChangedEventData, ICartItemRemovedEventData, ICartLoadedEventData, ICartProductAddEventData, ICartProductAddFailedEventData, ICartPromoCodeEventData, ICartPromoCodeFailedEventData, ICartShopRetailerEventData, ICartUpdatedEventData } from '@/core/pubsub/interfaces/cart.interface';
3
- import type { ICheckoutBillingInformationUpdatedEventData, ICheckoutCustomerInformationUpdatedEventData, ICheckoutDeliveryMethodUpdatedEventData, ICheckoutExpressCheckoutAvailabilityEventData, ICheckoutFailedEventData, ICheckoutGiftCardEventData, ICheckoutGiftCardFailedEventData, ICheckoutGiftInformationUpdatedEventData, ICheckoutItemEngravingUpdatedEventData, ICheckoutItemQuantityChangedEventData, ICheckoutItemRemovedEventData, ICheckoutLoadedEventData, ICheckoutMarketingPreferencesToggleEventData, ICheckoutProductAddEventData, ICheckoutProductAddFailedEventData, ICheckoutPromoCodeEventData, ICheckoutPromoCodeFailedEventData, ICheckoutSubmitCompletedEventData, ICheckoutSubmitFailedEventData, ICheckoutSubmitStartedEventData, ICheckoutTipUpdatedEventData, ICheckoutToggleEventData } from '@/core/pubsub/interfaces/checkout.interface';
3
+ import type { ICheckoutBillingInformationUpdatedEventData, ICheckoutCustomerInformationUpdatedEventData, ICheckoutDeliveryMethodUpdatedEventData, ICheckoutExpressCheckoutAvailabilityEventData, ICheckoutFailedEventData, ICheckoutGiftCardEventData, ICheckoutGiftCardFailedEventData, ICheckoutGiftInformationUpdatedEventData, ICheckoutItemEngravingUpdatedEventData, ICheckoutItemQuantityChangedEventData, ICheckoutItemRemovedEventData, ICheckoutLoadedEventData, ICheckoutMarketingPreferencesToggleEventData, ICheckoutPaymentFormFailedEventData, ICheckoutProductAddEventData, ICheckoutProductAddFailedEventData, ICheckoutPromoCodeEventData, ICheckoutPromoCodeFailedEventData, ICheckoutSubmitCompletedEventData, ICheckoutSubmitFailedEventData, ICheckoutSubmitStartedEventData, ICheckoutTipUpdatedEventData, ICheckoutToggleEventData } from '@/core/pubsub/interfaces/checkout.interface';
4
4
  import type { IProductAddToCartEventData, IProductFulfillmentChangedEventData, IProductFulfillmentTypeChangedEventData, IProductLoadedEventData, IProductQuantityChangedEventData, IProductSizeChangedEventData } from '@/core/pubsub/interfaces/product.interface';
5
5
  import { ELEMENTS_ACTIONS_EVENT } from '@/enums';
6
6
  export interface IElementsClientIsReadyEventData {
@@ -83,6 +83,7 @@ export interface IElementsActionsEventsMap {
83
83
  [ELEMENTS_ACTIONS_EVENT.CHECKOUT_PRODUCT_ADD_SUCCESS]: ICheckoutProductAddEventData;
84
84
  [ELEMENTS_ACTIONS_EVENT.CHECKOUT_PRODUCT_ADD_FAILED]: ICheckoutProductAddFailedEventData;
85
85
  [ELEMENTS_ACTIONS_EVENT.CHECKOUT_EXPRESS_CHECKOUT_AVAILABILITY]: ICheckoutExpressCheckoutAvailabilityEventData;
86
+ [ELEMENTS_ACTIONS_EVENT.CHECKOUT_PAYMENT_FORM_FAILED]: ICheckoutPaymentFormFailedEventData;
86
87
  }
87
88
  export type SpecificActionEvent = keyof IElementsActionsEventsMap;
88
89
  export interface IFormEventData {
@@ -61,6 +61,7 @@ export declare const ELEMENTS_ACTIONS_EVENT: {
61
61
  readonly CHECKOUT_PRODUCT_ADD_SUCCESS: "checkout_product_add_success";
62
62
  readonly CHECKOUT_PRODUCT_ADD_FAILED: "checkout_product_add_failed";
63
63
  readonly CHECKOUT_EXPRESS_CHECKOUT_AVAILABILITY: "checkout_express_checkout_availability";
64
+ readonly CHECKOUT_PAYMENT_FORM_FAILED: "checkout_payment_form_failed";
64
65
  };
65
66
  export declare const ELEMENTS_FORM: {
66
67
  readonly CUSTOMER: "customer";
@@ -12,6 +12,7 @@ export declare class AddressInputComponent extends BaseComponent<IAddressInputCo
12
12
  private selectedAddress;
13
13
  private searchTimeout?;
14
14
  private minSearchLength;
15
+ private placesSessionToken;
15
16
  private inputElement;
16
17
  private suggestionsContainer;
17
18
  private errorContainer;
@@ -5,8 +5,8 @@ export declare class AddressCommands extends BaseCommand {
5
5
  private cartCommands;
6
6
  constructor();
7
7
  static getInstance(): AddressCommands;
8
- searchAddresses(query: string): Promise<IAddressAutocompleteResult[]>;
9
- getAddressDetails(addressId: string): Promise<IAddressDetailsResult | null>;
8
+ searchAddresses(query: string, sessionToken?: string): Promise<IAddressAutocompleteResult[]>;
9
+ getAddressDetails(addressId: string, sessionToken?: string): Promise<IAddressDetailsResult | null>;
10
10
  setSelectedAddress(addressData: IAddressData): Promise<void>;
11
11
  setAddressManually(address: IAddressAddress, coordinates: IAddressCoordinates): Promise<void>;
12
12
  clearSelectedAddress(): Promise<void>;
@@ -6,6 +6,7 @@ import type { CheckoutPaymentSessionType, ICheckoutBilling, ICheckoutCustomer, I
6
6
  import type { AddItemParams } from '@/modules/cart/cart.commands';
7
7
  import type { PresaleExpiredReason } from '@/modules/checkout/components';
8
8
  import { type IExpressWalletBillingDetails } from '@/modules/checkout/express-wallet';
9
+ import type { StripeJsLoadFailure } from '@/modules/checkout/stripe-js';
9
10
  export declare class CheckoutCommands extends BaseCommand {
10
11
  private readonly uiCommands;
11
12
  private lastLoadParams;
@@ -51,6 +52,7 @@ export declare class CheckoutCommands extends BaseCommand {
51
52
  private applySavedMarketingPreferences;
52
53
  toggleMarketingPreferences(fieldName: 'canEmail' | 'canSms', active?: boolean): Promise<boolean>;
53
54
  getPaymentSession(): Promise<void>;
55
+ reportPaymentFormFailure(reason: StripeJsLoadFailure, cause?: unknown): void;
54
56
  getExpressPaymentSession(): Promise<ICheckoutPaymentSession | null>;
55
57
  private requestPaymentSession;
56
58
  confirmPaymentSession(confirmationTokenId: string, setupIntentId: string, sessionType?: CheckoutPaymentSessionType): Promise<ICheckoutPaymentMethodStore>;
@@ -54,7 +54,6 @@ export declare class CheckoutExpressCheckoutComponent extends BaseComponent<IChe
54
54
  private toBillingDetails;
55
55
  private failPayment;
56
56
  private handleCancel;
57
- private loadStripeJS;
58
57
  private teardownExpressElement;
59
58
  private remountIfTotalMoved;
60
59
  protected disconnected(): void;
@@ -55,5 +55,4 @@ export declare class CheckoutStripeFormComponent extends SafeHTMLElement {
55
55
  disconnected(): Promise<void>;
56
56
  disconnectedCallback(): void;
57
57
  private cleanupForm;
58
- private loadStripeJS;
59
58
  }
@@ -20,6 +20,7 @@ export declare class CheckoutStripeHandlerComponent extends BaseComponent<ICheck
20
20
  private isCreatingStripeForm;
21
21
  private stripeFormContainer;
22
22
  private stripeSummaryContainer;
23
+ private loadFailureNotice;
23
24
  private callbacks;
24
25
  private stripeFormStatus;
25
26
  private isInEditMode;
@@ -38,6 +39,9 @@ export declare class CheckoutStripeHandlerComponent extends BaseComponent<ICheck
38
39
  private hideStripeSummary;
39
40
  private showStripeForm;
40
41
  private hideStripeForm;
42
+ private showLoadFailure;
43
+ private clearLoadFailure;
44
+ private retryStripeForm;
41
45
  private handleChangePayment;
42
46
  protected template(): HTMLElement[];
43
47
  submitStripeForm(): void;
@@ -0,0 +1,2 @@
1
+ export type StripeJsLoadFailure = 'blocked' | 'timeout' | 'error';
2
+ export declare function loadStripeJs(): Promise<StripeJsLoadFailure | null>;
@@ -0,0 +1 @@
1
+ export declare function createPlacesSessionToken(): string;
@@ -9,7 +9,7 @@ Set address using a Google Places ID.
9
9
  ### Signature
10
10
 
11
11
  ```typescript
12
- setAddressByPlacesId(placesId: string): Promise<void>
12
+ setAddressByPlacesId(placesId: string, sessionToken?: string): Promise<void>
13
13
  ```
14
14
 
15
15
  ### Parameters
@@ -17,6 +17,7 @@ setAddressByPlacesId(placesId: string): Promise<void>
17
17
  | Parameter | Type | Required | Description |
18
18
  |-----------|------|----------|-------------|
19
19
  | `placesId` | string | Yes | Google Places ID |
20
+ | `sessionToken` | string | No | Google Places session token of the autocomplete requests that returned `placesId`. The details request ends that session, so Google bills the autocomplete requests as one session instead of per request. Applies only when the autocomplete requests used an API key in the same Google Cloud project as LiquidCommerce's address service. |
20
21
 
21
22
  ### Example
22
23
 
@@ -24,6 +25,9 @@ setAddressByPlacesId(placesId: string): Promise<void>
24
25
  await window.LiquidCommerce.elements.actions.address.setAddressByPlacesId(
25
26
  'ChIJOwg_06VPwokRYv534QaPC8g'
26
27
  );
28
+
29
+ // With the session token your own Places Autocomplete requests used
30
+ await window.LiquidCommerce.elements.actions.address.setAddressByPlacesId(placesId, sessionToken);
27
31
  ```
28
32
 
29
33
  ### How to Get Places ID
@@ -106,6 +106,7 @@ Content that appears or changes without navigation is announced through a shared
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
108
  | Express checkout payment failed | "Express checkout failed. …" |
109
+ | Card form could not load Stripe.js | The reason and what to do, e.g. "Your cookie settings are blocking our secure payment form. …" (assertive) |
109
110
  | Product list filtered or searched | "12 products found, showing 12" |
110
111
  | Validation failed | The field name and the error, interrupting (assertive) |
111
112
  | Carousel image changed | "Image 2 of 4" |
@@ -268,6 +269,8 @@ for (const region of document.querySelectorAll('[data-lce-live-region]')) {
268
269
 
269
270
  Checkout announces loading or initialization failure in a status region. If initialization fails, payment fields are withheld and a keyboard-operable **Retry checkout** button retries the same checkout. The button is disabled while loading.
270
271
 
272
+ If the card form cannot load Stripe.js — a consent tool holding the script back, a blocker, or a failed request — the reason and a keyboard-operable **Try again** button take the card form's place, and the message is announced assertively. While a retry runs the button stays focusable (`aria-disabled`, not `disabled`), so focus is not lost; if the retry fails, focus moves to the new **Try again** button, and if it succeeds, to the card form's container.
273
+
271
274
  Save Payment Information remains disabled until checkout initializes. During payment save it stays busy until the server responds. Recoverable billing/prepare errors are announced while the mounted card fields and billing input remain available for correction and retry.
272
275
 
273
276
  ### Wallet payment actions
@@ -56,6 +56,12 @@ The recommended method - provides accurate geocoding:
56
56
  await window.LiquidCommerce.elements.actions.address.setAddressByPlacesId('ChIJOwg_06VPwokRYv534QaPC8g');
57
57
  ```
58
58
 
59
+ If you run Google Places Autocomplete yourself with a [session token](https://developers.google.com/maps/documentation/places/web-service/session-tokens), pass the same token as the second argument. The details request then ends your session, and Google bills the autocomplete requests as one session instead of per request. Google only groups requests whose API keys belong to the same Google Cloud project, so this applies only when your autocomplete requests used the same project as LiquidCommerce's address service; a token from autocomplete requests made with an API key in another project doesn't change billing:
60
+
61
+ ```javascript
62
+ await window.LiquidCommerce.elements.actions.address.setAddressByPlacesId(placesId, sessionToken);
63
+ ```
64
+
59
65
  **How to get a Places ID:**
60
66
 
61
67
  Visit [Google Place IDs](https://developers.google.com/maps/documentation/places/web-service/place-id#find-id) for details on obtaining a Places ID.
@@ -411,6 +411,12 @@ window.addEventListener('lce:actions.checkout_submit_failed', (event) => {
411
411
  console.error('Payment failed:', message);
412
412
  // Show error message
413
413
  });
414
+
415
+ // The card form could not load Stripe.js (fires again for each failed Try again)
416
+ window.addEventListener('lce:actions.checkout_payment_form_failed', (event) => {
417
+ const { reason } = event.detail.data; // 'blocked' | 'timeout' | 'error'
418
+ console.warn('Card form unavailable:', reason);
419
+ });
414
420
  ```
415
421
 
416
422
  ### Express Checkout
@@ -522,6 +528,35 @@ The SDK uses Stripe for payment processing. Payment form is embedded and handles
522
528
 
523
529
  No additional Stripe integration code needed - it's built-in.
524
530
 
531
+ ### Cookie consent and Content Security Policy
532
+
533
+ The card form runs on Stripe.js, which the SDK loads from `https://js.stripe.com` when the payment
534
+ step opens. Two things on a host page can stop it loading:
535
+
536
+ - **Cookie-consent tools with auto-blocking** (OneTrust, Cookiebot and similar) hold back every
537
+ script in a category the shopper has not accepted. If Stripe is filed under anything other than
538
+ strictly necessary, a shopper who declines that category cannot pay by card. Classify Stripe — the
539
+ `js.stripe.com` script and the cookies it sets — as **Strictly Necessary**, or exclude it from
540
+ auto-blocking. Card payment does not work without it.
541
+ - **A Content Security Policy** has to allow Stripe.js: `https://js.stripe.com` in `script-src` and
542
+ `frame-src`, and `https://api.stripe.com` in `connect-src`. Stripe's
543
+ [CSP guidance](https://docs.stripe.com/security/guide#content-security-policy) lists the full set.
544
+
545
+ When Stripe.js cannot load, or loads but cannot build the card form, the shopper sees a message and a **Try again** button where the card form
546
+ would be, rather than an empty space. A script held back by a consent tool asks them to allow
547
+ cookies; a load that stalled or failed points them at their connection or an ad blocker. The SDK also
548
+ fires [`lce:actions.checkout_payment_form_failed`](./events.md) with a `reason` of `blocked`, `timeout`
549
+ or `error`, so the page can respond:
550
+
551
+ ```javascript
552
+ window.addEventListener('lce:actions.checkout_payment_form_failed', (event) => {
553
+ const { reason } = event.detail.data;
554
+ if (reason === 'blocked') {
555
+ // Stripe is held back by consent settings: reopen your consent tool's preferences here.
556
+ }
557
+ });
558
+ ```
559
+
525
560
  ### Express checkout (Apple Pay and Google Pay)
526
561
 
527
562
  Apple Pay and Google Pay are offered as express checkout buttons at the top of the checkout, above
@@ -730,10 +765,16 @@ checkout: {
730
765
 
731
766
  ### Payment Form Not Loading
732
767
 
768
+ If the Payment section reads "Your cookie settings are blocking our secure payment form", a consent
769
+ tool on the page is holding Stripe.js back — see
770
+ [Cookie consent and Content Security Policy](#cookie-consent-and-content-security-policy).
771
+ Otherwise:
772
+
733
773
  1. Check internet connection (Stripe requires network)
734
- 2. Verify Stripe is not blocked by ad blockers
735
- 3. Check browser console for Stripe errors
736
- 4. Ensure your API key is valid
774
+ 2. Verify Stripe is not blocked by ad blockers or the page's Content Security Policy
775
+ 3. Listen for `lce:actions.checkout_payment_form_failed` and check its `reason`
776
+ 4. Check browser console for Stripe errors
777
+ 5. Ensure your API key is valid
737
778
 
738
779
  ### Customer Info Not Pre-filling
739
780
 
@@ -893,6 +893,29 @@ window.addEventListener('lce:actions.checkout_express_checkout_availability', (e
893
893
  });
894
894
  ```
895
895
 
896
+ ### `lce:actions.checkout_payment_form_failed`
897
+
898
+ Fires when the card form cannot load Stripe.js, so the card fields cannot appear. The shopper sees a
899
+ message and a **Try again** button where the card form would be; each attempt that fails fires the
900
+ event again. `reason` is `blocked` when something on the page held the script back before it was
901
+ fetched — typically a cookie-consent tool with auto-blocking, for a shopper who has not accepted the
902
+ category Stripe is filed under — and `timeout` or `error` when the load stalled or failed (`error` also when Stripe.js loads but cannot
903
+ build the card form, as when `api.stripe.com` is blocked). See
904
+ [Cookie consent and Content Security Policy](./checkout-component.md#cookie-consent-and-content-security-policy).
905
+
906
+ **Data includes:** `cartId`, `reason` (`'blocked' | 'timeout' | 'error'`).
907
+
908
+ **Example**
909
+
910
+ ```javascript
911
+ window.addEventListener('lce:actions.checkout_payment_form_failed', (event) => {
912
+ const { data } = event.detail;
913
+ if (data.reason === 'blocked') {
914
+ // For example, reopen your consent tool's preferences so the shopper can allow Stripe.
915
+ }
916
+ });
917
+ ```
918
+
896
919
  ### `lce:actions.checkout_product_add_success`
897
920
 
898
921
  Fires when products are added to checkout via the actions API.
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.7.42",
6
+ "version": "2.7.43",
7
7
  "homepage": "https://docs.liquidcommerce.co/elements-sdk",
8
8
  "repository": {
9
9
  "type": "git",