@funnelsgrove/payments 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -40,11 +40,11 @@ Shared billing and checkout helpers for funnels.
|
|
|
40
40
|
- the `StripeExpressCheckoutElement` wrapper, which keeps `Elements` provider ownership inside this package so catalog funnels with their own dependency installs do not pass Stripe promises across duplicate local Stripe type copies
|
|
41
41
|
- `src/providers/paymentProvider.types.ts` for provider-neutral checkout preparation state and provider ids
|
|
42
42
|
- `src/providers/stripe/useStripeSubscriptionCheckoutSession.ts` for Stripe SDK initialization, publishable-key resolution, subscription client-secret preparation, card/wallet loading state, and friendly checkout errors
|
|
43
|
-
- `src/providers/stripe/ApplePaySubscriptionCheckoutSlot.tsx` and `src/providers/stripe/GooglePaySubscriptionCheckoutSlot.tsx` for
|
|
43
|
+
- `src/providers/stripe/ApplePaySubscriptionCheckoutSlot.tsx` and `src/providers/stripe/GooglePaySubscriptionCheckoutSlot.tsx` for disabled loading wallet shells that prepare Stripe Express Checkout on load and swap in Stripe's real wallet controls when available
|
|
44
44
|
- Stripe subscription checkout sessions reuse the active client secret across card checkout and paywall wallet checkout for the same intent key, so opening the embedded checkout after a paywall wallet button is ready does not create a second subscription session.
|
|
45
45
|
- Stripe Express Checkout elements must stay mounted and measurable until Stripe reports availability; only hide the container after `onReady` or `onLoadError` reports that the requested wallet method is unavailable.
|
|
46
46
|
- Shared checkout dialogs must switch to card checkout when Stripe reports no requested wallet availability, so an unavailable Apple Pay or Google Pay shell never leaves a fake wallet tab blocking the card form.
|
|
47
|
-
- Wallet slots should show placeholder
|
|
47
|
+
- Wallet slots should show disabled grey placeholder shells only while availability is unknown; after Stripe reports unavailable, the placeholder must disappear instead of opening a card checkout under wallet branding.
|
|
48
48
|
- Checkout v2 owns only real Stripe Elements for card and wallet collection: Stripe controls the card-field placeholders, Stripe's `ExpressCheckoutElement` controls Apple Pay / Google Pay availability, desktop web can expose both wallet icons, and mobile narrows to Apple Pay on iOS or Google Pay on Android.
|
|
49
49
|
- Checkout v2 can receive a paywall-confirmed wallet availability hint and seed its wallet tab from that state, letting a checkout reopen keep Apple Pay or Google Pay visible while its own Express Checkout element remounts against the same client secret.
|
|
50
50
|
- Checkout v2 renders the wallet tab icons from the active platform wallet list and keeps Apple Pay / Google Pay marks large enough to read inside the tab.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx,
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { StripeExpressCheckoutElement } from '../../components/shared/StripeExpressCheckoutElement.js';
|
|
5
5
|
export function WalletSubscriptionCheckoutSlot({ amountCents, availabilityPaymentMethod, beforeConfirm, className, customerEmail, customerName, disabled = false, expressCheckoutAllowed = true, onAvailabilityChange, onError, onSuccess, onUnavailableClick, options, placeholderLabel, renderPlaceholder, returnUrl, session, summaryLabel, suspended = false, }) {
|
|
@@ -12,6 +12,12 @@ export function WalletSubscriptionCheckoutSlot({ amountCents, availabilityPaymen
|
|
|
12
12
|
const walletAvailable = walletAvailability.intentKey === session.intentKey
|
|
13
13
|
? walletAvailability.available
|
|
14
14
|
: null;
|
|
15
|
+
const shouldRenderPlaceholder = !suspended && expressCheckoutAllowed && walletAvailable === null;
|
|
16
|
+
const shouldRenderExpressCheckout = !suspended &&
|
|
17
|
+
expressCheckoutAllowed &&
|
|
18
|
+
walletAvailable !== false &&
|
|
19
|
+
Boolean(session.activeClientSecret) &&
|
|
20
|
+
Boolean(session.stripePromise);
|
|
15
21
|
useEffect(() => {
|
|
16
22
|
if (slotDisabled ||
|
|
17
23
|
suspended ||
|
|
@@ -54,16 +60,30 @@ export function WalletSubscriptionCheckoutSlot({ amountCents, availabilityPaymen
|
|
|
54
60
|
}
|
|
55
61
|
await session.prepareWalletCheckout();
|
|
56
62
|
};
|
|
57
|
-
return (_jsxs(_Fragment, { children: [
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
return (_jsxs(_Fragment, { children: [shouldRenderPlaceholder || shouldRenderExpressCheckout ? (_jsxs("div", { className: [
|
|
64
|
+
'wallet-subscription-checkout-slot',
|
|
65
|
+
shouldRenderPlaceholder ? 'is-loading' : '',
|
|
66
|
+
]
|
|
67
|
+
.filter(Boolean)
|
|
68
|
+
.join(' '), "aria-busy": shouldRenderPlaceholder || undefined, children: [shouldRenderExpressCheckout &&
|
|
69
|
+
session.activeClientSecret &&
|
|
70
|
+
session.stripePromise ? (_jsx(StripeExpressCheckoutElement, { amountCents: amountCents, availabilityPaymentMethods: [availabilityPaymentMethod], beforeConfirm: beforeConfirm, className: className, clientSecret: session.activeClientSecret, customerEmail: customerEmail, customerName: customerName, onAvailabilityChange: handleAvailabilityChange, onError: handleError, onSuccess: onSuccess, options: options, returnUrl: returnUrl, stripePromise: session.stripePromise, summaryLabel: summaryLabel })) : null, shouldRenderPlaceholder ? (_jsx("div", { className: 'wallet-subscription-checkout-slot__placeholder', children: renderPlaceholder({
|
|
71
|
+
className,
|
|
72
|
+
disabled: true,
|
|
73
|
+
label: placeholderLabel,
|
|
74
|
+
onClick: () => void handlePlaceholderClick(),
|
|
75
|
+
}) })) : null] })) : null, _jsx("style", { children: walletSubscriptionCheckoutSlotStyles })] }));
|
|
69
76
|
}
|
|
77
|
+
const walletSubscriptionCheckoutSlotStyles = `
|
|
78
|
+
.wallet-subscription-checkout-slot {
|
|
79
|
+
position: relative;
|
|
80
|
+
width: 100%;
|
|
81
|
+
min-height: var(--wallet-subscription-checkout-slot-min-height, 64px);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.wallet-subscription-checkout-slot__placeholder {
|
|
85
|
+
position: absolute;
|
|
86
|
+
inset: 0;
|
|
87
|
+
z-index: 1;
|
|
88
|
+
}
|
|
89
|
+
`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@funnelsgrove/payments",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"test:run": "vitest run --passWithNoTests"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@funnelsgrove/runtime": "0.1.
|
|
29
|
+
"@funnelsgrove/runtime": "0.1.2",
|
|
30
30
|
"@stripe/react-stripe-js": "^5.6.0",
|
|
31
31
|
"@stripe/stripe-js": "^8.7.0",
|
|
32
32
|
"react": "19.2.3",
|