@funnelsgrove/payments 0.1.30 → 0.1.32

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.
@@ -1,6 +1,19 @@
1
1
  import { type ReactNode } from 'react';
2
2
  import type { AvailablePaymentMethods, StripeCheckoutExpressCheckoutElementOptions } from '@stripe/stripe-js';
3
3
  import { type StripeSubscriptionCheckoutSession } from './useStripeSubscriptionCheckoutSession.js';
4
+ export type WalletSubscriptionCheckoutRenderStateInput = {
5
+ expressCheckoutAllowed: boolean;
6
+ hasActiveClientSecret: boolean;
7
+ hasStripePromise: boolean;
8
+ suspended: boolean;
9
+ walletAvailable: boolean | null;
10
+ };
11
+ export type WalletSubscriptionCheckoutRenderState = {
12
+ placeholderIsPreparing: boolean;
13
+ shouldRenderExpressCheckout: boolean;
14
+ shouldRenderPlaceholder: boolean;
15
+ };
16
+ export declare function getWalletSubscriptionCheckoutRenderState({ expressCheckoutAllowed, hasActiveClientSecret, hasStripePromise, suspended, walletAvailable, }: WalletSubscriptionCheckoutRenderStateInput): WalletSubscriptionCheckoutRenderState;
4
17
  type WalletPlaceholderButtonProps = {
5
18
  className?: string;
6
19
  disabled: boolean;
@@ -3,6 +3,22 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { useCallback, useEffect, useRef, useState } from 'react';
4
4
  import { StripeExpressCheckoutElement } from '../../components/shared/StripeExpressCheckoutElement.js';
5
5
  import { isInactiveCheckoutSessionError, } from './useStripeSubscriptionCheckoutSession.js';
6
+ export function getWalletSubscriptionCheckoutRenderState({ expressCheckoutAllowed, hasActiveClientSecret, hasStripePromise, suspended, walletAvailable, }) {
7
+ const shouldRenderExpressCheckout = !suspended &&
8
+ expressCheckoutAllowed &&
9
+ walletAvailable !== false &&
10
+ hasActiveClientSecret &&
11
+ hasStripePromise;
12
+ const shouldRenderPlaceholder = !shouldRenderExpressCheckout &&
13
+ !suspended &&
14
+ expressCheckoutAllowed &&
15
+ walletAvailable === null;
16
+ return {
17
+ placeholderIsPreparing: shouldRenderPlaceholder,
18
+ shouldRenderExpressCheckout,
19
+ shouldRenderPlaceholder,
20
+ };
21
+ }
6
22
  export function WalletSubscriptionCheckoutLoadingPlaceholder({ className, label, }) {
7
23
  return (_jsxs("div", { className: [
8
24
  'wallet-subscription-checkout-slot__loading',
@@ -21,16 +37,13 @@ export function WalletSubscriptionCheckoutSlot({ amountCents, availabilityPaymen
21
37
  const walletAvailable = walletAvailability.intentKey === session.intentKey
22
38
  ? walletAvailability.available
23
39
  : null;
24
- const shouldRenderExpressCheckout = !suspended &&
25
- expressCheckoutAllowed &&
26
- walletAvailable !== false &&
27
- Boolean(session.activeClientSecret) &&
28
- Boolean(session.stripePromise);
29
- const shouldRenderPlaceholder = !shouldRenderExpressCheckout &&
30
- !suspended &&
31
- expressCheckoutAllowed &&
32
- walletAvailable === null;
33
- const placeholderIsPreparing = shouldRenderPlaceholder;
40
+ const { placeholderIsPreparing, shouldRenderExpressCheckout, shouldRenderPlaceholder, } = getWalletSubscriptionCheckoutRenderState({
41
+ expressCheckoutAllowed,
42
+ hasActiveClientSecret: Boolean(session.activeClientSecret),
43
+ hasStripePromise: Boolean(session.stripePromise),
44
+ suspended,
45
+ walletAvailable,
46
+ });
34
47
  const serverUpdateKey = session.activeClientSecret &&
35
48
  session.checkoutSessionId &&
36
49
  session.activePlanKey !== session.planKey
@@ -35,5 +35,10 @@ export type StripeSubscriptionCheckoutSession = {
35
35
  stripePromise: Promise<Stripe | null> | null;
36
36
  updateCheckoutSessionPlan: () => Promise<boolean>;
37
37
  };
38
+ export type StripeSubscriptionCheckoutIntentKeyInput = Pick<StripeSubscriptionCheckoutSessionInput, 'checkoutMode' | 'couponId' | 'customerEmail' | 'returnUrl' | 'runtimeConfig' | 'userId'> & {
39
+ analyticsMetadata?: Record<string, unknown> | null;
40
+ };
41
+ export declare function buildStripeSubscriptionCheckoutIntentKey({ checkoutMode, couponId, customerEmail, returnUrl, runtimeConfig, userId, }: StripeSubscriptionCheckoutIntentKeyInput): string;
42
+ export declare function shouldResetStripeSubscriptionCheckoutSessionForIntentKey(previousIntentKey: string | null, nextIntentKey: string): boolean;
38
43
  export declare function isInactiveCheckoutSessionError(message?: string | null): boolean;
39
44
  export declare function useStripeSubscriptionCheckoutSession({ checkoutMode, analyticsMetadata, couponId, customerEmail, displayPlan, enabled, onError, plan, returnUrl, runtimeConfig, userId, }: StripeSubscriptionCheckoutSessionInput): StripeSubscriptionCheckoutSession;
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
2
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
3
3
  import { createEmptyCheckoutPreparationLoading, } from '../paymentProvider.types.js';
4
4
  import { createStripeSubscriptionCheckout, getStripePromise, isStripeConfigured, updateStripeSubscriptionCheckoutPlan, } from '../../services/stripe.service.js';
5
5
  const getFriendlyStripeCheckoutError = (error) => {
@@ -9,6 +9,29 @@ const getFriendlyStripeCheckoutError = (error) => {
9
9
  : message;
10
10
  };
11
11
  const normalizeRuntimeConfigValue = (value) => (value === null || value === void 0 ? void 0 : value.trim()) || '';
12
+ const useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect;
13
+ export function buildStripeSubscriptionCheckoutIntentKey({ checkoutMode, couponId, customerEmail, returnUrl, runtimeConfig, userId, }) {
14
+ const runtimeConfigSignature = [
15
+ normalizeRuntimeConfigValue(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.apiBaseUrl),
16
+ normalizeRuntimeConfigValue(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.funnelId),
17
+ normalizeRuntimeConfigValue(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.funnelVersionId),
18
+ normalizeRuntimeConfigValue(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.funnelSdkPublishableKey),
19
+ ].join('|');
20
+ const customerEmailSignature = normalizeRuntimeConfigValue(customerEmail);
21
+ const userIdSignature = normalizeRuntimeConfigValue(userId);
22
+ return [
23
+ 'stripe',
24
+ checkoutMode,
25
+ runtimeConfigSignature,
26
+ customerEmailSignature,
27
+ userIdSignature,
28
+ (couponId === null || couponId === void 0 ? void 0 : couponId.trim()) || '',
29
+ returnUrl.trim(),
30
+ ].join('|');
31
+ }
32
+ export function shouldResetStripeSubscriptionCheckoutSessionForIntentKey(previousIntentKey, nextIntentKey) {
33
+ return previousIntentKey !== null && previousIntentKey !== nextIntentKey;
34
+ }
12
35
  export function isInactiveCheckoutSessionError(message) {
13
36
  var _a;
14
37
  return /\bcheckout session\b.*\bno longer active\b/i.test((_a = message === null || message === void 0 ? void 0 : message.trim()) !== null && _a !== void 0 ? _a : '');
@@ -24,26 +47,17 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, analyticsMe
24
47
  const [runtimeStripePublishableKey, setRuntimeStripePublishableKey] = useState(null);
25
48
  const creatingIntentRef = useRef(null);
26
49
  const requestIdRef = useRef(0);
27
- const runtimeConfigSignature = [
28
- normalizeRuntimeConfigValue(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.apiBaseUrl),
29
- normalizeRuntimeConfigValue(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.funnelId),
30
- normalizeRuntimeConfigValue(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.funnelVersionId),
31
- normalizeRuntimeConfigValue(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.funnelSdkPublishableKey),
32
- ].join('|');
33
- const customerEmailSignature = normalizeRuntimeConfigValue(customerEmail);
34
- const userIdSignature = normalizeRuntimeConfigValue(userId);
35
50
  const configured = enabled &&
36
51
  (isStripeConfigured(checkoutMode) ||
37
52
  Boolean(normalizeRuntimeConfigValue(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.funnelSdkPublishableKey)));
38
- const intentKey = [
39
- 'stripe',
53
+ const intentKey = buildStripeSubscriptionCheckoutIntentKey({
40
54
  checkoutMode,
41
- runtimeConfigSignature,
42
- customerEmailSignature,
43
- userIdSignature,
44
- (couponId === null || couponId === void 0 ? void 0 : couponId.trim()) || '',
45
- returnUrl.trim(),
46
- ].join('|');
55
+ couponId,
56
+ customerEmail,
57
+ returnUrl,
58
+ runtimeConfig,
59
+ userId,
60
+ });
47
61
  const planKey = [
48
62
  (_a = plan === null || plan === void 0 ? void 0 : plan.id) !== null && _a !== void 0 ? _a : '',
49
63
  (_b = plan === null || plan === void 0 ? void 0 : plan.providerPlanId) !== null && _b !== void 0 ? _b : '',
@@ -55,6 +69,7 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, analyticsMe
55
69
  const activeCheckoutSessionId = clientSecretIntentKey === intentKey ? checkoutSessionId : null;
56
70
  const activePlanKey = clientSecretIntentKey === intentKey ? clientSecretPlanKey : null;
57
71
  const stripePromise = useMemo(() => getStripePromise(checkoutMode, runtimeStripePublishableKey), [checkoutMode, runtimeStripePublishableKey]);
72
+ const previousIntentKeyRef = useRef(intentKey);
58
73
  const clearActiveCheckoutSession = useCallback(() => {
59
74
  requestIdRef.current += 1;
60
75
  creatingIntentRef.current = null;
@@ -79,8 +94,12 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, analyticsMe
79
94
  setRuntimeStripePublishableKey(null);
80
95
  setError(null);
81
96
  }, [clearActiveCheckoutSession, setError]);
82
- useEffect(() => {
83
- reset();
97
+ useIsomorphicLayoutEffect(() => {
98
+ const previousIntentKey = previousIntentKeyRef.current;
99
+ previousIntentKeyRef.current = intentKey;
100
+ if (shouldResetStripeSubscriptionCheckoutSessionForIntentKey(previousIntentKey, intentKey)) {
101
+ reset();
102
+ }
84
103
  }, [intentKey, reset]);
85
104
  const setSourceLoading = useCallback((source, value) => {
86
105
  setLoading((current) => current[source] === value
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelsgrove/payments",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "main": "./dist/index.js",