@funnelsgrove/payments 0.1.36 → 0.1.38
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 +5 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/services/checkoutCompletionAnalytics.service.d.ts +12 -0
- package/dist/services/checkoutCompletionAnalytics.service.js +74 -0
- package/dist/services/stripe.service.d.ts +14 -0
- package/dist/services/stripe.service.js +25 -0
- package/package.json +2 -1
- package/dist/components/shared/PaywallSubscriptionCheckout.d.ts +0 -146
- package/dist/components/shared/PaywallSubscriptionCheckout.js +0 -340
package/README.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Shared billing and checkout helpers for funnels.
|
|
4
4
|
|
|
5
|
+
Detailed implementation docs:
|
|
6
|
+
|
|
7
|
+
- [Shared Payments](../../docs/funnel-sdk/shared-payments.md)
|
|
8
|
+
- [Funnel API payment endpoints](../../docs/funnel-sdk/funnel-api.md#checkout-endpoints)
|
|
9
|
+
|
|
5
10
|
## Build And Publish
|
|
6
11
|
|
|
7
12
|
- Build distributable output with `npm run build --workspace @funnelsgrove/payments`.
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from './services/planCatalog.service.js';
|
|
|
5
5
|
export * from './services/runtimeBillingPlanCatalog.service.js';
|
|
6
6
|
export * from './services/paywallOffer.service.js';
|
|
7
7
|
export * from './services/stripe.service.js';
|
|
8
|
+
export * from './services/checkoutCompletionAnalytics.service.js';
|
|
8
9
|
export * from './hooks/useResolvedPaywallPlans.js';
|
|
9
10
|
export * from './providers/paymentProvider.types.js';
|
|
10
11
|
export * from './providers/stripe/useStripeSubscriptionCheckoutSession.js';
|
|
@@ -14,7 +15,6 @@ export * from './providers/stripe/GooglePaySubscriptionCheckoutSlot.js';
|
|
|
14
15
|
export { ManageSubscriptionScreen, type ManageSubscriptionContent, type ManageSubscriptionScreenProps, } from './components/ManageSubscriptionScreen.js';
|
|
15
16
|
export * from './components/shared/SharedStripeCheckoutDialog.js';
|
|
16
17
|
export * from './components/shared/SharedStripeCheckoutV2Dialog.js';
|
|
17
|
-
export * from './components/shared/PaywallSubscriptionCheckout.js';
|
|
18
18
|
export * from './components/shared/ApplePaySubscribeButton.js';
|
|
19
19
|
export * from './components/shared/GooglePaySubscribeButton.js';
|
|
20
20
|
export * from './components/shared/StripeCheckoutExpressCheckoutButton.js';
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export * from './services/planCatalog.service.js';
|
|
|
5
5
|
export * from './services/runtimeBillingPlanCatalog.service.js';
|
|
6
6
|
export * from './services/paywallOffer.service.js';
|
|
7
7
|
export * from './services/stripe.service.js';
|
|
8
|
+
export * from './services/checkoutCompletionAnalytics.service.js';
|
|
8
9
|
export * from './hooks/useResolvedPaywallPlans.js';
|
|
9
10
|
export * from './providers/paymentProvider.types.js';
|
|
10
11
|
export * from './providers/stripe/useStripeSubscriptionCheckoutSession.js';
|
|
@@ -14,7 +15,6 @@ export * from './providers/stripe/GooglePaySubscriptionCheckoutSlot.js';
|
|
|
14
15
|
export { ManageSubscriptionScreen, } from './components/ManageSubscriptionScreen.js';
|
|
15
16
|
export * from './components/shared/SharedStripeCheckoutDialog.js';
|
|
16
17
|
export * from './components/shared/SharedStripeCheckoutV2Dialog.js';
|
|
17
|
-
export * from './components/shared/PaywallSubscriptionCheckout.js';
|
|
18
18
|
export * from './components/shared/ApplePaySubscribeButton.js';
|
|
19
19
|
export * from './components/shared/GooglePaySubscribeButton.js';
|
|
20
20
|
export * from './components/shared/StripeCheckoutExpressCheckoutButton.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RuntimeMode } from '@funnelsgrove/runtime';
|
|
2
|
+
import { type StripeRuntimeConfigOverrides } from './stripe.service.js';
|
|
3
|
+
export type TrackPaidStripeSubscriptionCheckoutCompletedInput = {
|
|
4
|
+
checkoutSessionId?: string | null;
|
|
5
|
+
environment?: RuntimeMode;
|
|
6
|
+
metadata?: Record<string, unknown> | null;
|
|
7
|
+
runtimeConfig?: StripeRuntimeConfigOverrides;
|
|
8
|
+
stepId?: string;
|
|
9
|
+
stepName?: string;
|
|
10
|
+
};
|
|
11
|
+
export type TrackPaidStripeSubscriptionCheckoutCompletedResult = 'already_tracked' | 'missing_checkout_session' | 'tracked' | 'unpaid';
|
|
12
|
+
export declare function trackPaidStripeSubscriptionCheckoutCompleted(input: TrackPaidStripeSubscriptionCheckoutCompletedInput): Promise<TrackPaidStripeSubscriptionCheckoutCompletedResult>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { publicAnalyticsSdk, } from '@funnelsgrove/analytics';
|
|
2
|
+
import { verifyStripeSubscriptionCheckoutPayment, } from './stripe.service.js';
|
|
3
|
+
const asRecord = (value) => {
|
|
4
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
5
|
+
? value
|
|
6
|
+
: {};
|
|
7
|
+
};
|
|
8
|
+
const activeCheckoutCompletionKeys = new Set();
|
|
9
|
+
const buildCheckoutCompletedStorageKey = (checkoutSessionId, runtimeConfig) => {
|
|
10
|
+
var _a;
|
|
11
|
+
const funnelId = ((_a = runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.funnelId) === null || _a === void 0 ? void 0 : _a.trim()) || 'unknown_funnel';
|
|
12
|
+
return `funnelsgrove:checkout_completed:${funnelId}:${checkoutSessionId}`;
|
|
13
|
+
};
|
|
14
|
+
const hasTrackedCheckoutSession = (checkoutSessionId, runtimeConfig) => {
|
|
15
|
+
var _a;
|
|
16
|
+
if (typeof window === 'undefined') {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
return Boolean((_a = window.sessionStorage) === null || _a === void 0 ? void 0 : _a.getItem(buildCheckoutCompletedStorageKey(checkoutSessionId, runtimeConfig)));
|
|
21
|
+
}
|
|
22
|
+
catch (_b) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const markCheckoutSessionTracked = (checkoutSessionId, runtimeConfig) => {
|
|
27
|
+
var _a;
|
|
28
|
+
if (typeof window === 'undefined') {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
(_a = window.sessionStorage) === null || _a === void 0 ? void 0 : _a.setItem(buildCheckoutCompletedStorageKey(checkoutSessionId, runtimeConfig), '1');
|
|
33
|
+
}
|
|
34
|
+
catch (_b) {
|
|
35
|
+
// A stable checkout-session event id still protects provider-side dedupe.
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
export async function trackPaidStripeSubscriptionCheckoutCompleted(input) {
|
|
39
|
+
var _a;
|
|
40
|
+
const checkoutSessionId = ((_a = input.checkoutSessionId) === null || _a === void 0 ? void 0 : _a.trim()) || '';
|
|
41
|
+
if (!checkoutSessionId) {
|
|
42
|
+
return 'missing_checkout_session';
|
|
43
|
+
}
|
|
44
|
+
const completionKey = buildCheckoutCompletedStorageKey(checkoutSessionId, input.runtimeConfig);
|
|
45
|
+
if (activeCheckoutCompletionKeys.has(completionKey) ||
|
|
46
|
+
hasTrackedCheckoutSession(checkoutSessionId, input.runtimeConfig)) {
|
|
47
|
+
return 'already_tracked';
|
|
48
|
+
}
|
|
49
|
+
activeCheckoutCompletionKeys.add(completionKey);
|
|
50
|
+
try {
|
|
51
|
+
const checkoutStatus = await verifyStripeSubscriptionCheckoutPayment({
|
|
52
|
+
checkoutSessionId,
|
|
53
|
+
environment: input.environment,
|
|
54
|
+
runtimeConfig: input.runtimeConfig,
|
|
55
|
+
});
|
|
56
|
+
if (!checkoutStatus.paid) {
|
|
57
|
+
return 'unpaid';
|
|
58
|
+
}
|
|
59
|
+
const analyticsMetadata = asRecord(checkoutStatus.analyticsMetadata);
|
|
60
|
+
const conversionInput = {
|
|
61
|
+
eventId: checkoutSessionId,
|
|
62
|
+
stepId: input.stepId,
|
|
63
|
+
stepName: input.stepName,
|
|
64
|
+
metadata: Object.assign(Object.assign(Object.assign({}, asRecord(input.metadata)), analyticsMetadata), { checkoutSessionId, checkout_session_id: checkoutSessionId, checkout_session_status: checkoutStatus.status || undefined, payment_status: checkoutStatus.paymentStatus || undefined, environment: checkoutStatus.environment || input.environment || analyticsMetadata.environment }),
|
|
65
|
+
};
|
|
66
|
+
publicAnalyticsSdk.trackCheckoutCompleted(conversionInput);
|
|
67
|
+
markCheckoutSessionTracked(checkoutSessionId, input.runtimeConfig);
|
|
68
|
+
await publicAnalyticsSdk.flush().catch(() => 0);
|
|
69
|
+
return 'tracked';
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
activeCheckoutCompletionKeys.delete(completionKey);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -119,8 +119,22 @@ type UpdateSubscriptionCheckoutPlanResponse = {
|
|
|
119
119
|
checkoutSessionId: string;
|
|
120
120
|
environment?: 'test' | 'live';
|
|
121
121
|
};
|
|
122
|
+
export type VerifySubscriptionCheckoutPaymentInput = {
|
|
123
|
+
checkoutSessionId: string;
|
|
124
|
+
environment?: RuntimeMode;
|
|
125
|
+
runtimeConfig?: StripeRuntimeConfigOverrides;
|
|
126
|
+
};
|
|
127
|
+
export type VerifySubscriptionCheckoutPaymentResponse = {
|
|
128
|
+
checkoutSessionId: string;
|
|
129
|
+
paid: boolean;
|
|
130
|
+
paymentStatus?: string | null;
|
|
131
|
+
status?: string | null;
|
|
132
|
+
environment?: 'test' | 'live';
|
|
133
|
+
analyticsMetadata?: Record<string, unknown>;
|
|
134
|
+
};
|
|
122
135
|
export declare function createStripeSubscriptionCheckout(input: CreateSubscriptionCheckoutInput): Promise<CreateSubscriptionCheckoutResponse>;
|
|
123
136
|
export declare function updateStripeSubscriptionCheckoutPlan(input: UpdateSubscriptionCheckoutPlanInput): Promise<UpdateSubscriptionCheckoutPlanResponse>;
|
|
137
|
+
export declare function verifyStripeSubscriptionCheckoutPayment(input: VerifySubscriptionCheckoutPaymentInput): Promise<VerifySubscriptionCheckoutPaymentResponse>;
|
|
124
138
|
type CreateCheckoutSessionInput = {
|
|
125
139
|
plan: CheckoutSessionPlanInput;
|
|
126
140
|
successUrl: string;
|
|
@@ -714,6 +714,31 @@ export async function updateStripeSubscriptionCheckoutPlan(input) {
|
|
|
714
714
|
}
|
|
715
715
|
return (await response.json());
|
|
716
716
|
}
|
|
717
|
+
export async function verifyStripeSubscriptionCheckoutPayment(input) {
|
|
718
|
+
const checkoutSessionId = input.checkoutSessionId.trim();
|
|
719
|
+
if (!checkoutSessionId) {
|
|
720
|
+
throw new Error('checkoutSessionId is required');
|
|
721
|
+
}
|
|
722
|
+
const runtimeConfig = resolveStripeRuntimeConfig(input.runtimeConfig);
|
|
723
|
+
const response = await fetch(buildStripeRuntimeApiUrl('/sdk/public/payments/subscriptions/checkout-session-status', runtimeConfig), {
|
|
724
|
+
method: 'POST',
|
|
725
|
+
headers: buildStripeRuntimeHeaders(runtimeConfig, {
|
|
726
|
+
'Content-Type': 'application/json',
|
|
727
|
+
}),
|
|
728
|
+
body: JSON.stringify({
|
|
729
|
+
publishableKey: runtimeConfig.funnelSdkPublishableKey || undefined,
|
|
730
|
+
funnelId: runtimeConfig.funnelId || undefined,
|
|
731
|
+
funnelVersionId: runtimeConfig.funnelVersionId || undefined,
|
|
732
|
+
checkoutSessionId,
|
|
733
|
+
environment: input.environment || undefined,
|
|
734
|
+
}),
|
|
735
|
+
});
|
|
736
|
+
if (!response.ok) {
|
|
737
|
+
const errorMessage = await parseErrorMessage(response, 'Unable to verify subscription checkout');
|
|
738
|
+
throw new Error(errorMessage);
|
|
739
|
+
}
|
|
740
|
+
return (await response.json());
|
|
741
|
+
}
|
|
717
742
|
export async function createStripeCheckoutSession(input) {
|
|
718
743
|
var _a, _b, _c, _d, _e;
|
|
719
744
|
const recurring = resolveCheckoutPlanRecurringConfig(input.plan);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@funnelsgrove/payments",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.38",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"test:run": "vitest run --passWithNoTests"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@funnelsgrove/analytics": "^0.1.13",
|
|
30
31
|
"@funnelsgrove/runtime": "^0.1.18",
|
|
31
32
|
"@stripe/react-stripe-js": "^5.6.0",
|
|
32
33
|
"@stripe/stripe-js": "^8.7.0",
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { type FormEvent } from 'react';
|
|
2
|
-
import type { RuntimeMode } from '@funnelsgrove/runtime';
|
|
3
|
-
import type { StripeRuntimeConfigOverrides, PaywallPlan } from '../../services/stripe.service.js';
|
|
4
|
-
import type { PaywallDisplayPlan } from '../../services/paywallOffer.service.js';
|
|
5
|
-
import { type PlatformWalletPaymentMethod } from './walletPlatform.js';
|
|
6
|
-
import { type StripeSubscriptionCheckoutSession } from '../../providers/stripe/useStripeSubscriptionCheckoutSession.js';
|
|
7
|
-
export type PaywallSubscriptionCheckoutContent = {
|
|
8
|
-
title: string;
|
|
9
|
-
closeAriaLabel: string;
|
|
10
|
-
walletButtonLabel: string;
|
|
11
|
-
customerEmailLabel: string;
|
|
12
|
-
customerEmailPlaceholder: string;
|
|
13
|
-
customerEmailInvalidMessage: string;
|
|
14
|
-
walletEmailPromptTitle: string;
|
|
15
|
-
walletEmailPromptDescription: string;
|
|
16
|
-
walletEmailPromptSubmitLabel: string;
|
|
17
|
-
walletEmailPromptCancelLabel: string;
|
|
18
|
-
countdownLabel: string;
|
|
19
|
-
satisfactionPercent: string;
|
|
20
|
-
satisfactionLabel: string;
|
|
21
|
-
originalPriceLabel: string;
|
|
22
|
-
discountRowLabelTemplate: string;
|
|
23
|
-
promoCodeLabel: string;
|
|
24
|
-
savedLabelTemplate: string;
|
|
25
|
-
totalLabel: string;
|
|
26
|
-
cardSubmitLabel: string;
|
|
27
|
-
paypalLabel: string;
|
|
28
|
-
paypalButtonLabel: string;
|
|
29
|
-
processingLabel: string;
|
|
30
|
-
secureLabel: string;
|
|
31
|
-
paymentMethodLabels: readonly string[];
|
|
32
|
-
specialOffer: {
|
|
33
|
-
image?: {
|
|
34
|
-
src?: string;
|
|
35
|
-
alt?: string;
|
|
36
|
-
};
|
|
37
|
-
discountLabel: string;
|
|
38
|
-
title: string;
|
|
39
|
-
description: string;
|
|
40
|
-
buttonLabel: string;
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
export type PaywallSubscriptionPaymentStackContent = {
|
|
44
|
-
cardButtonLabel: string;
|
|
45
|
-
googlePayPlaceholderLabel: string;
|
|
46
|
-
metaLabels: readonly string[];
|
|
47
|
-
stripeUnavailableNote: string;
|
|
48
|
-
supportText: string;
|
|
49
|
-
walletPlaceholderLabel: string;
|
|
50
|
-
};
|
|
51
|
-
type PaywallCheckoutCloseDiscountState = {
|
|
52
|
-
stage: string;
|
|
53
|
-
status: string;
|
|
54
|
-
};
|
|
55
|
-
export type UsePaywallSubscriptionCheckoutControllerInput = {
|
|
56
|
-
analyticsMetadata?: Record<string, unknown> | null;
|
|
57
|
-
appliedDiscountAmountCents: number;
|
|
58
|
-
checkoutDiscountPercent: number;
|
|
59
|
-
checkoutMode: RuntimeMode;
|
|
60
|
-
checkoutPromoActive: boolean;
|
|
61
|
-
content: PaywallSubscriptionCheckoutContent;
|
|
62
|
-
customerEmailEditable: boolean;
|
|
63
|
-
customerName?: string | null;
|
|
64
|
-
discountState?: PaywallCheckoutCloseDiscountState | null;
|
|
65
|
-
initialCustomerEmail?: string | null;
|
|
66
|
-
onCheckoutCompleted?: () => Promise<void> | void;
|
|
67
|
-
onCheckoutStarted?: () => Promise<void> | void;
|
|
68
|
-
onCustomerEmailCommit: (email: string) => Promise<string>;
|
|
69
|
-
onFirstCheckoutClosed?: () => void;
|
|
70
|
-
plan: PaywallPlan | null;
|
|
71
|
-
returnUrl: string;
|
|
72
|
-
runtimeConfig?: StripeRuntimeConfigOverrides;
|
|
73
|
-
selectedDisplayPlan: PaywallDisplayPlan | null;
|
|
74
|
-
supportEmail: string;
|
|
75
|
-
userId?: string | null;
|
|
76
|
-
getReturnUrl?: (checkoutSessionId?: string | null) => string;
|
|
77
|
-
};
|
|
78
|
-
export type PaywallSubscriptionCheckoutController = {
|
|
79
|
-
checkoutDialogOpen: boolean;
|
|
80
|
-
checkoutDialogReady: boolean;
|
|
81
|
-
checkoutDisabled: boolean;
|
|
82
|
-
checkoutDiscountAmountLabel: string;
|
|
83
|
-
checkoutDiscountLabel: string;
|
|
84
|
-
checkoutInitialWalletAvailable: boolean | null;
|
|
85
|
-
checkoutSavedLabel: string;
|
|
86
|
-
checkoutSession: StripeSubscriptionCheckoutSession;
|
|
87
|
-
checkoutSuccessReturnUrl: string;
|
|
88
|
-
checkoutSummaryLabel: string;
|
|
89
|
-
checkoutTotalValue: string;
|
|
90
|
-
closeCheckoutDialog: () => void;
|
|
91
|
-
commitCheckoutEmail: (draftEmail: string) => Promise<string>;
|
|
92
|
-
customerEmail: string;
|
|
93
|
-
customerEmailEditable: boolean;
|
|
94
|
-
customerName: string;
|
|
95
|
-
error: string | null;
|
|
96
|
-
handleApplePayAvailabilityChange: (available: boolean) => void;
|
|
97
|
-
handleGooglePayAvailabilityChange: (available: boolean) => void;
|
|
98
|
-
openCardCheckoutFromUnavailableWallet: () => Promise<void>;
|
|
99
|
-
preparePaywallWalletCheckout: () => Promise<string | null>;
|
|
100
|
-
setCheckoutEmail: (value: string) => void;
|
|
101
|
-
startCheckout: () => Promise<void>;
|
|
102
|
-
supportEmail: string;
|
|
103
|
-
trackCheckoutCompleted: () => Promise<void>;
|
|
104
|
-
walletEmailPromptCancel: () => void;
|
|
105
|
-
walletEmailPromptDraft: string;
|
|
106
|
-
walletEmailPromptError: string | null;
|
|
107
|
-
walletEmailPromptOpen: boolean;
|
|
108
|
-
walletEmailPromptSubmit: (event: FormEvent<HTMLFormElement>) => Promise<void>;
|
|
109
|
-
walletPaymentMethods: readonly PlatformWalletPaymentMethod[];
|
|
110
|
-
setWalletEmailPromptDraft: (value: string) => void;
|
|
111
|
-
};
|
|
112
|
-
export declare function usePaywallSubscriptionCheckoutController({ analyticsMetadata, appliedDiscountAmountCents, checkoutDiscountPercent, checkoutMode, checkoutPromoActive, content, customerEmailEditable, customerName, discountState, getReturnUrl, initialCustomerEmail, onCheckoutCompleted, onCheckoutStarted, onCustomerEmailCommit, onFirstCheckoutClosed, plan, returnUrl, runtimeConfig, selectedDisplayPlan, supportEmail, userId, }: UsePaywallSubscriptionCheckoutControllerInput): PaywallSubscriptionCheckoutController;
|
|
113
|
-
export type PaywallSubscriptionCheckoutDialogsProps = {
|
|
114
|
-
buttonColor?: string;
|
|
115
|
-
content: PaywallSubscriptionCheckoutContent;
|
|
116
|
-
controller: PaywallSubscriptionCheckoutController;
|
|
117
|
-
discountPercent: number;
|
|
118
|
-
promoActive: boolean;
|
|
119
|
-
promoDisplayName: string;
|
|
120
|
-
remainingSeconds: number;
|
|
121
|
-
selectedDisplayPlan: PaywallDisplayPlan | null;
|
|
122
|
-
specialOfferDialogOpen: boolean;
|
|
123
|
-
themeColor?: string;
|
|
124
|
-
onSpecialOfferAccept: () => void;
|
|
125
|
-
};
|
|
126
|
-
export declare function PaywallSubscriptionCheckoutDialogs({ buttonColor, content, controller, discountPercent, promoActive, promoDisplayName, remainingSeconds, selectedDisplayPlan, specialOfferDialogOpen, themeColor, onSpecialOfferAccept, }: PaywallSubscriptionCheckoutDialogsProps): import("react/jsx-runtime").JSX.Element;
|
|
127
|
-
export type PaywallSubscriptionPaymentStackProps = {
|
|
128
|
-
applePayButtonClassName?: string;
|
|
129
|
-
applePayShellClassName?: string;
|
|
130
|
-
cardButtonClassName?: string;
|
|
131
|
-
className?: string;
|
|
132
|
-
content: PaywallSubscriptionPaymentStackContent;
|
|
133
|
-
controller: PaywallSubscriptionCheckoutController;
|
|
134
|
-
disclaimerClassName?: string;
|
|
135
|
-
errorClassName?: string;
|
|
136
|
-
googlePayButtonClassName?: string;
|
|
137
|
-
googlePayShellClassName?: string;
|
|
138
|
-
metaClassName?: string;
|
|
139
|
-
noteClassName?: string;
|
|
140
|
-
paymentDisclaimer: string;
|
|
141
|
-
selectedDisplayPlan: PaywallDisplayPlan | null;
|
|
142
|
-
supportClassName?: string;
|
|
143
|
-
walletSuspended: boolean;
|
|
144
|
-
};
|
|
145
|
-
export declare function PaywallSubscriptionPaymentStack({ applePayButtonClassName, applePayShellClassName, cardButtonClassName, className, content, controller, disclaimerClassName, errorClassName, googlePayButtonClassName, googlePayShellClassName, metaClassName, noteClassName, paymentDisclaimer, selectedDisplayPlan, supportClassName, walletSuspended, }: PaywallSubscriptionPaymentStackProps): import("react/jsx-runtime").JSX.Element;
|
|
146
|
-
export {};
|
|
@@ -1,340 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
-
import { ApplePaySubscriptionCheckoutSlot, } from '../../providers/stripe/ApplePaySubscriptionCheckoutSlot.js';
|
|
5
|
-
import { GooglePaySubscriptionCheckoutSlot, } from '../../providers/stripe/GooglePaySubscriptionCheckoutSlot.js';
|
|
6
|
-
import { SharedCheckoutSpecialOfferDialog, SharedStripeCheckoutV2Dialog, } from './SharedStripeCheckoutV2Dialog.js';
|
|
7
|
-
import { usePlatformWalletPaymentMethods } from './walletPlatform.js';
|
|
8
|
-
import { useStripeSubscriptionCheckoutSession, } from '../../providers/stripe/useStripeSubscriptionCheckoutSession.js';
|
|
9
|
-
const checkoutCurrencyFormatter = new Intl.NumberFormat('en-US', {
|
|
10
|
-
currency: 'USD',
|
|
11
|
-
maximumFractionDigits: 2,
|
|
12
|
-
minimumFractionDigits: 2,
|
|
13
|
-
style: 'currency',
|
|
14
|
-
});
|
|
15
|
-
function formatCheckoutAmount(amountCents) {
|
|
16
|
-
return checkoutCurrencyFormatter.format(amountCents / 100);
|
|
17
|
-
}
|
|
18
|
-
function getErrorMessage(error, fallback) {
|
|
19
|
-
return error instanceof Error && error.message ? error.message : fallback;
|
|
20
|
-
}
|
|
21
|
-
export function usePaywallSubscriptionCheckoutController({ analyticsMetadata, appliedDiscountAmountCents, checkoutDiscountPercent, checkoutMode, checkoutPromoActive, content, customerEmailEditable, customerName, discountState, getReturnUrl, initialCustomerEmail, onCheckoutCompleted, onCheckoutStarted, onCustomerEmailCommit, onFirstCheckoutClosed, plan, returnUrl, runtimeConfig, selectedDisplayPlan, supportEmail, userId, }) {
|
|
22
|
-
var _a, _b, _c, _d;
|
|
23
|
-
const walletPaymentMethods = usePlatformWalletPaymentMethods();
|
|
24
|
-
const [checkoutDialogOpen, setCheckoutDialogOpen] = useState(false);
|
|
25
|
-
const [checkoutEmail, setCheckoutEmail] = useState((_a = initialCustomerEmail === null || initialCustomerEmail === void 0 ? void 0 : initialCustomerEmail.trim()) !== null && _a !== void 0 ? _a : '');
|
|
26
|
-
const [error, setError] = useState(null);
|
|
27
|
-
const [paywallWalletAvailability, setPaywallWalletAvailability] = useState({
|
|
28
|
-
intentKey: '',
|
|
29
|
-
methods: {},
|
|
30
|
-
});
|
|
31
|
-
const [walletEmailPromptOpen, setWalletEmailPromptOpen] = useState(false);
|
|
32
|
-
const [walletEmailPromptDraft, setWalletEmailPromptDraft] = useState('');
|
|
33
|
-
const [walletEmailPromptError, setWalletEmailPromptError] = useState(null);
|
|
34
|
-
const walletEmailResolverRef = useRef(null);
|
|
35
|
-
const checkoutSummaryLabel = ((_b = selectedDisplayPlan === null || selectedDisplayPlan === void 0 ? void 0 : selectedDisplayPlan.checkoutSummaryLabel) === null || _b === void 0 ? void 0 : _b.trim()) || (selectedDisplayPlan === null || selectedDisplayPlan === void 0 ? void 0 : selectedDisplayPlan.title) || 'Selected plan';
|
|
36
|
-
const checkoutDiscountLabel = checkoutPromoActive
|
|
37
|
-
? content.discountRowLabelTemplate.replace('{percent}', String(checkoutDiscountPercent))
|
|
38
|
-
: '';
|
|
39
|
-
const checkoutDiscountAmountLabel = checkoutPromoActive
|
|
40
|
-
? `-${formatCheckoutAmount(appliedDiscountAmountCents)}`
|
|
41
|
-
: '';
|
|
42
|
-
const checkoutSavedLabel = checkoutPromoActive
|
|
43
|
-
? content.savedLabelTemplate
|
|
44
|
-
.replace('{amount}', formatCheckoutAmount(appliedDiscountAmountCents))
|
|
45
|
-
.replace('{percent}', String(checkoutDiscountPercent))
|
|
46
|
-
: '';
|
|
47
|
-
const checkoutTotalValue = useMemo(() => {
|
|
48
|
-
var _a;
|
|
49
|
-
if (!selectedDisplayPlan) {
|
|
50
|
-
return '';
|
|
51
|
-
}
|
|
52
|
-
return ((_a = selectedDisplayPlan.priceLabel.split('/')[0]) === null || _a === void 0 ? void 0 : _a.trim()) || selectedDisplayPlan.priceLabel;
|
|
53
|
-
}, [selectedDisplayPlan]);
|
|
54
|
-
const successReturnUrl = useMemo(() => (getReturnUrl === null || getReturnUrl === void 0 ? void 0 : getReturnUrl()) || returnUrl, [getReturnUrl, returnUrl]);
|
|
55
|
-
const checkoutSession = useStripeSubscriptionCheckoutSession({
|
|
56
|
-
analyticsMetadata,
|
|
57
|
-
checkoutMode,
|
|
58
|
-
couponId: checkoutPromoActive ? (_c = selectedDisplayPlan === null || selectedDisplayPlan === void 0 ? void 0 : selectedDisplayPlan.couponId) !== null && _c !== void 0 ? _c : null : null,
|
|
59
|
-
customerEmail: checkoutEmail || initialCustomerEmail,
|
|
60
|
-
displayPlan: selectedDisplayPlan,
|
|
61
|
-
onError: setError,
|
|
62
|
-
plan,
|
|
63
|
-
returnUrl: successReturnUrl,
|
|
64
|
-
runtimeConfig,
|
|
65
|
-
userId,
|
|
66
|
-
});
|
|
67
|
-
const checkoutDisabled = !checkoutSession.configured || !plan || !selectedDisplayPlan || !userId;
|
|
68
|
-
const checkoutDialogReady = checkoutDialogOpen &&
|
|
69
|
-
Boolean(checkoutSession.activeClientSecret) &&
|
|
70
|
-
Boolean(checkoutSession.stripePromise) &&
|
|
71
|
-
Boolean(selectedDisplayPlan);
|
|
72
|
-
const checkoutSuccessReturnUrl = useMemo(() => (getReturnUrl === null || getReturnUrl === void 0 ? void 0 : getReturnUrl(checkoutSession.checkoutSessionId)) || returnUrl, [checkoutSession.checkoutSessionId, getReturnUrl, returnUrl]);
|
|
73
|
-
const currentPaywallWalletAvailability = paywallWalletAvailability.intentKey === checkoutSession.intentKey
|
|
74
|
-
? paywallWalletAvailability.methods
|
|
75
|
-
: {};
|
|
76
|
-
const checkoutInitialWalletAvailable = walletPaymentMethods.some((method) => currentPaywallWalletAvailability[method] === true)
|
|
77
|
-
? true
|
|
78
|
-
: null;
|
|
79
|
-
useEffect(() => {
|
|
80
|
-
const timeoutId = window.setTimeout(() => {
|
|
81
|
-
var _a;
|
|
82
|
-
setCheckoutEmail((_a = initialCustomerEmail === null || initialCustomerEmail === void 0 ? void 0 : initialCustomerEmail.trim()) !== null && _a !== void 0 ? _a : '');
|
|
83
|
-
}, 0);
|
|
84
|
-
return () => window.clearTimeout(timeoutId);
|
|
85
|
-
}, [initialCustomerEmail]);
|
|
86
|
-
useEffect(() => {
|
|
87
|
-
return () => {
|
|
88
|
-
var _a;
|
|
89
|
-
(_a = walletEmailResolverRef.current) === null || _a === void 0 ? void 0 : _a.call(walletEmailResolverRef, null);
|
|
90
|
-
walletEmailResolverRef.current = null;
|
|
91
|
-
};
|
|
92
|
-
}, []);
|
|
93
|
-
const updatePaywallWalletAvailability = (method, available) => {
|
|
94
|
-
setPaywallWalletAvailability((current) => {
|
|
95
|
-
const currentMethods = current.intentKey === checkoutSession.intentKey ? current.methods : {};
|
|
96
|
-
return {
|
|
97
|
-
intentKey: checkoutSession.intentKey,
|
|
98
|
-
methods: Object.assign(Object.assign({}, currentMethods), { [method]: available }),
|
|
99
|
-
};
|
|
100
|
-
});
|
|
101
|
-
};
|
|
102
|
-
const handleApplePayAvailabilityChange = (available) => updatePaywallWalletAvailability('applePay', available);
|
|
103
|
-
const handleGooglePayAvailabilityChange = (available) => updatePaywallWalletAvailability('googlePay', available);
|
|
104
|
-
const trackCheckoutStarted = async () => {
|
|
105
|
-
await (onCheckoutStarted === null || onCheckoutStarted === void 0 ? void 0 : onCheckoutStarted());
|
|
106
|
-
};
|
|
107
|
-
const startCheckout = async () => {
|
|
108
|
-
if (checkoutDisabled || checkoutSession.loading.card) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
await trackCheckoutStarted();
|
|
112
|
-
if (checkoutSession.activeClientSecret) {
|
|
113
|
-
setCheckoutDialogOpen(true);
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
const readyClientSecret = await checkoutSession.prepareCardCheckout();
|
|
117
|
-
if (readyClientSecret) {
|
|
118
|
-
setCheckoutDialogOpen(true);
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
const trackCheckoutCompleted = async () => {
|
|
122
|
-
await (onCheckoutCompleted === null || onCheckoutCompleted === void 0 ? void 0 : onCheckoutCompleted());
|
|
123
|
-
};
|
|
124
|
-
const commitCheckoutEmail = async (draftEmail) => {
|
|
125
|
-
var _a;
|
|
126
|
-
const normalizedEmail = draftEmail.trim();
|
|
127
|
-
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(normalizedEmail)) {
|
|
128
|
-
throw new Error(content.customerEmailInvalidMessage);
|
|
129
|
-
}
|
|
130
|
-
if (normalizedEmail === ((_a = initialCustomerEmail === null || initialCustomerEmail === void 0 ? void 0 : initialCustomerEmail.trim()) !== null && _a !== void 0 ? _a : '')) {
|
|
131
|
-
setCheckoutEmail(normalizedEmail);
|
|
132
|
-
return normalizedEmail;
|
|
133
|
-
}
|
|
134
|
-
const syncedEmail = await onCustomerEmailCommit(normalizedEmail);
|
|
135
|
-
const committedEmail = syncedEmail.trim() || normalizedEmail;
|
|
136
|
-
setCheckoutEmail(committedEmail);
|
|
137
|
-
return committedEmail;
|
|
138
|
-
};
|
|
139
|
-
const resolveWalletEmailPrompt = useCallback((email) => {
|
|
140
|
-
var _a;
|
|
141
|
-
(_a = walletEmailResolverRef.current) === null || _a === void 0 ? void 0 : _a.call(walletEmailResolverRef, email);
|
|
142
|
-
walletEmailResolverRef.current = null;
|
|
143
|
-
}, []);
|
|
144
|
-
const requestWalletEmail = useCallback(async () => {
|
|
145
|
-
setWalletEmailPromptDraft(checkoutEmail.trim() || (initialCustomerEmail === null || initialCustomerEmail === void 0 ? void 0 : initialCustomerEmail.trim()) || '');
|
|
146
|
-
setWalletEmailPromptError(null);
|
|
147
|
-
setWalletEmailPromptOpen(true);
|
|
148
|
-
return await new Promise((resolve) => {
|
|
149
|
-
walletEmailResolverRef.current = resolve;
|
|
150
|
-
});
|
|
151
|
-
}, [checkoutEmail, initialCustomerEmail]);
|
|
152
|
-
const walletEmailPromptSubmit = async (event) => {
|
|
153
|
-
event.preventDefault();
|
|
154
|
-
try {
|
|
155
|
-
const committedEmail = await commitCheckoutEmail(walletEmailPromptDraft);
|
|
156
|
-
setWalletEmailPromptOpen(false);
|
|
157
|
-
setWalletEmailPromptError(null);
|
|
158
|
-
resolveWalletEmailPrompt(committedEmail);
|
|
159
|
-
}
|
|
160
|
-
catch (submitError) {
|
|
161
|
-
setWalletEmailPromptError(getErrorMessage(submitError, content.customerEmailInvalidMessage));
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
const walletEmailPromptCancel = () => {
|
|
165
|
-
setWalletEmailPromptOpen(false);
|
|
166
|
-
setWalletEmailPromptError(null);
|
|
167
|
-
resolveWalletEmailPrompt(null);
|
|
168
|
-
};
|
|
169
|
-
const preparePaywallWalletCheckout = async () => {
|
|
170
|
-
await trackCheckoutStarted();
|
|
171
|
-
const normalizedEmail = checkoutEmail.trim() || (initialCustomerEmail === null || initialCustomerEmail === void 0 ? void 0 : initialCustomerEmail.trim()) || '';
|
|
172
|
-
if (!normalizedEmail) {
|
|
173
|
-
return await requestWalletEmail();
|
|
174
|
-
}
|
|
175
|
-
return normalizedEmail;
|
|
176
|
-
};
|
|
177
|
-
const openCardCheckoutFromUnavailableWallet = async () => {
|
|
178
|
-
var _a;
|
|
179
|
-
if (checkoutDisabled || checkoutSession.loading.card) {
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
await trackCheckoutStarted();
|
|
183
|
-
const readyClientSecret = (_a = checkoutSession.activeClientSecret) !== null && _a !== void 0 ? _a : await checkoutSession.prepareCardCheckout();
|
|
184
|
-
if (readyClientSecret) {
|
|
185
|
-
setCheckoutDialogOpen(true);
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
const closeCheckoutDialog = () => {
|
|
189
|
-
setCheckoutDialogOpen(false);
|
|
190
|
-
setError(null);
|
|
191
|
-
if ((discountState === null || discountState === void 0 ? void 0 : discountState.stage) === 'first' && discountState.status === 'active') {
|
|
192
|
-
onFirstCheckoutClosed === null || onFirstCheckoutClosed === void 0 ? void 0 : onFirstCheckoutClosed();
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
|
-
return {
|
|
196
|
-
checkoutDialogOpen,
|
|
197
|
-
checkoutDialogReady,
|
|
198
|
-
checkoutDisabled,
|
|
199
|
-
checkoutDiscountAmountLabel,
|
|
200
|
-
checkoutDiscountLabel,
|
|
201
|
-
checkoutInitialWalletAvailable,
|
|
202
|
-
checkoutSavedLabel,
|
|
203
|
-
checkoutSession,
|
|
204
|
-
checkoutSuccessReturnUrl,
|
|
205
|
-
checkoutSummaryLabel,
|
|
206
|
-
checkoutTotalValue,
|
|
207
|
-
closeCheckoutDialog,
|
|
208
|
-
commitCheckoutEmail,
|
|
209
|
-
customerEmail: checkoutEmail,
|
|
210
|
-
customerEmailEditable,
|
|
211
|
-
customerName: (_d = customerName === null || customerName === void 0 ? void 0 : customerName.trim()) !== null && _d !== void 0 ? _d : '',
|
|
212
|
-
error,
|
|
213
|
-
handleApplePayAvailabilityChange,
|
|
214
|
-
handleGooglePayAvailabilityChange,
|
|
215
|
-
openCardCheckoutFromUnavailableWallet,
|
|
216
|
-
preparePaywallWalletCheckout,
|
|
217
|
-
setCheckoutEmail,
|
|
218
|
-
startCheckout,
|
|
219
|
-
supportEmail,
|
|
220
|
-
trackCheckoutCompleted,
|
|
221
|
-
walletEmailPromptCancel,
|
|
222
|
-
walletEmailPromptDraft,
|
|
223
|
-
walletEmailPromptError,
|
|
224
|
-
walletEmailPromptOpen,
|
|
225
|
-
walletEmailPromptSubmit,
|
|
226
|
-
walletPaymentMethods,
|
|
227
|
-
setWalletEmailPromptDraft,
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
export function PaywallSubscriptionCheckoutDialogs({ buttonColor = 'var(--color-secondary-text)', content, controller, discountPercent, promoActive, promoDisplayName, remainingSeconds, selectedDisplayPlan, specialOfferDialogOpen, themeColor = 'var(--color-secondary-text)', onSpecialOfferAccept, }) {
|
|
231
|
-
var _a, _b;
|
|
232
|
-
return (_jsxs(_Fragment, { children: [controller.checkoutDialogOpen &&
|
|
233
|
-
controller.checkoutSession.activeClientSecret &&
|
|
234
|
-
controller.checkoutSession.stripePromise &&
|
|
235
|
-
selectedDisplayPlan ? (_jsx(SharedStripeCheckoutV2Dialog, { amountCents: selectedDisplayPlan.amountCents, buttonColor: buttonColor, cardSubmitLabel: content.cardSubmitLabel, clientSecret: controller.checkoutSession.activeClientSecret, closeAriaLabel: content.closeAriaLabel, countdownLabel: content.countdownLabel, customerEmail: controller.customerEmail, customerEmailEditable: controller.customerEmailEditable, customerEmailLabel: content.customerEmailLabel, customerEmailPlaceholder: content.customerEmailPlaceholder, customerEmailInvalidMessage: content.customerEmailInvalidMessage, customerName: controller.customerName, discountAmountLabel: controller.checkoutDiscountAmountLabel, discountLabel: controller.checkoutDiscountLabel, discountPercent: discountPercent, initialWalletAvailable: controller.checkoutInitialWalletAvailable, onClose: controller.closeCheckoutDialog, onCustomerEmailChange: controller.setCheckoutEmail, onCustomerEmailCommit: controller.commitCheckoutEmail, onError: controller.checkoutSession.setError, onSuccess: controller.trackCheckoutCompleted, paymentMethodLabels: content.paymentMethodLabels, paypalButtonLabel: content.paypalButtonLabel, paypalLabel: content.paypalLabel, promoActive: promoActive, promoCode: promoDisplayName, promoCodeLabel: content.promoCodeLabel, processingLabel: content.processingLabel, remainingSeconds: remainingSeconds, returnUrl: controller.checkoutSuccessReturnUrl, savedLabel: controller.checkoutSavedLabel, secureLabel: content.secureLabel, satisfactionLabel: content.satisfactionLabel, satisfactionPercent: content.satisfactionPercent, stripePromise: controller.checkoutSession.stripePromise, summaryLabel: controller.checkoutSummaryLabel, themeColor: themeColor, title: content.title, totalLabel: content.totalLabel, totalValue: controller.checkoutTotalValue, walletButtonLabel: content.walletButtonLabel, originalPriceLabel: content.originalPriceLabel, originalPriceValue: selectedDisplayPlan.basePriceLabel })) : null, specialOfferDialogOpen ? (_jsx(SharedCheckoutSpecialOfferDialog, { buttonColor: buttonColor, buttonLabel: content.specialOffer.buttonLabel, description: content.specialOffer.description, discountLabel: content.specialOffer.discountLabel, imageAlt: (_a = content.specialOffer.image) === null || _a === void 0 ? void 0 : _a.alt, imageSrc: (_b = content.specialOffer.image) === null || _b === void 0 ? void 0 : _b.src, onAccept: onSpecialOfferAccept, themeColor: themeColor, title: content.specialOffer.title })) : null, controller.walletEmailPromptOpen ? (_jsx(PaywallWalletEmailPromptDialog, { content: content, draftEmail: controller.walletEmailPromptDraft, error: controller.walletEmailPromptError, onCancel: controller.walletEmailPromptCancel, onChange: controller.setWalletEmailPromptDraft, onSubmit: controller.walletEmailPromptSubmit })) : null] }));
|
|
236
|
-
}
|
|
237
|
-
export function PaywallSubscriptionPaymentStack({ applePayButtonClassName, applePayShellClassName, cardButtonClassName, className, content, controller, disclaimerClassName, errorClassName, googlePayButtonClassName, googlePayShellClassName, metaClassName, noteClassName, paymentDisclaimer, selectedDisplayPlan, supportClassName, walletSuspended, }) {
|
|
238
|
-
const suspended = controller.checkoutDialogReady || walletSuspended;
|
|
239
|
-
return (_jsxs("section", { className: className, children: [controller.walletPaymentMethods.includes('applePay') ? (_jsx("div", { className: applePayShellClassName, children: selectedDisplayPlan ? (_jsx(ApplePaySubscriptionCheckoutSlot, { amountCents: selectedDisplayPlan.amountCents, beforeConfirm: controller.preparePaywallWalletCheckout, className: applePayButtonClassName, customerEmail: controller.customerEmail, customerName: controller.customerName, disabled: controller.checkoutDisabled, onAvailabilityChange: controller.handleApplePayAvailabilityChange, onSuccess: controller.trackCheckoutCompleted, onUnavailableClick: controller.openCardCheckoutFromUnavailableWallet, placeholderLabel: content.walletPlaceholderLabel, returnUrl: controller.checkoutSuccessReturnUrl, session: controller.checkoutSession, summaryLabel: controller.checkoutSummaryLabel, suspended: suspended })) : null })) : null, controller.walletPaymentMethods.includes('googlePay') ? (_jsx("div", { className: googlePayShellClassName, children: selectedDisplayPlan ? (_jsx(GooglePaySubscriptionCheckoutSlot, { amountCents: selectedDisplayPlan.amountCents, beforeConfirm: controller.preparePaywallWalletCheckout, className: googlePayButtonClassName, customerEmail: controller.customerEmail, customerName: controller.customerName, disabled: controller.checkoutDisabled, onAvailabilityChange: controller.handleGooglePayAvailabilityChange, onSuccess: controller.trackCheckoutCompleted, onUnavailableClick: controller.openCardCheckoutFromUnavailableWallet, placeholderLabel: content.googlePayPlaceholderLabel, returnUrl: controller.checkoutSuccessReturnUrl, session: controller.checkoutSession, summaryLabel: controller.checkoutSummaryLabel, suspended: suspended })) : null })) : null, _jsx("button", { type: 'button', className: cardButtonClassName, onClick: () => void controller.startCheckout(), disabled: controller.checkoutDisabled || controller.checkoutSession.loading.card, children: content.cardButtonLabel }), _jsx("p", { className: metaClassName, children: content.metaLabels.join(' · ') }), _jsx("p", { className: disclaimerClassName, children: paymentDisclaimer }), _jsxs("p", { className: supportClassName, children: [content.supportText, ' ', _jsx("a", { href: `mailto:${controller.supportEmail}`, children: controller.supportEmail })] }), !controller.checkoutSession.configured ? (_jsx("p", { className: noteClassName, children: content.stripeUnavailableNote })) : null, controller.error ? _jsx("p", { className: errorClassName, children: controller.error }) : null] }));
|
|
240
|
-
}
|
|
241
|
-
function PaywallWalletEmailPromptDialog({ content, draftEmail, error, onCancel, onChange, onSubmit, }) {
|
|
242
|
-
return (_jsxs("div", { className: 'paywall-wallet-email-prompt-backdrop', role: 'presentation', children: [_jsxs("form", { className: 'paywall-wallet-email-prompt', role: 'dialog', "aria-modal": 'true', "aria-labelledby": 'paywall-wallet-email-prompt-title', onSubmit: (event) => void onSubmit(event), children: [_jsx("h2", { id: 'paywall-wallet-email-prompt-title', children: content.walletEmailPromptTitle }), _jsx("p", { children: content.walletEmailPromptDescription }), _jsxs("label", { children: [_jsx("span", { children: content.customerEmailLabel }), _jsx("input", { type: 'email', inputMode: 'email', autoComplete: 'email', value: draftEmail, onChange: (event) => onChange(event.currentTarget.value), placeholder: content.customerEmailPlaceholder, autoFocus: true })] }), error ? _jsx("p", { className: 'paywall-wallet-email-prompt-error', children: error }) : null, _jsxs("div", { className: 'paywall-wallet-email-prompt-actions', children: [_jsx("button", { type: 'button', onClick: onCancel, children: content.walletEmailPromptCancelLabel }), _jsx("button", { type: 'submit', children: content.walletEmailPromptSubmitLabel })] })] }), _jsx("style", { children: paywallWalletEmailPromptStyles })] }));
|
|
243
|
-
}
|
|
244
|
-
const paywallWalletEmailPromptStyles = `
|
|
245
|
-
.paywall-wallet-email-prompt-backdrop {
|
|
246
|
-
position: fixed;
|
|
247
|
-
inset: 0;
|
|
248
|
-
z-index: 1000;
|
|
249
|
-
display: flex;
|
|
250
|
-
align-items: center;
|
|
251
|
-
justify-content: center;
|
|
252
|
-
padding: 20px;
|
|
253
|
-
background: rgb(13 17 32 / 42%);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
.paywall-wallet-email-prompt {
|
|
257
|
-
box-sizing: border-box;
|
|
258
|
-
width: min(100%, 360px);
|
|
259
|
-
border-radius: 20px;
|
|
260
|
-
background: #fff;
|
|
261
|
-
padding: 22px;
|
|
262
|
-
box-shadow: 0 18px 48px rgb(19 27 47 / 26%);
|
|
263
|
-
color: #111827;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
.paywall-wallet-email-prompt h2 {
|
|
267
|
-
margin: 0;
|
|
268
|
-
color: #111827;
|
|
269
|
-
font-size: 22px;
|
|
270
|
-
font-weight: 800;
|
|
271
|
-
line-height: 1.15;
|
|
272
|
-
letter-spacing: 0;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
.paywall-wallet-email-prompt p {
|
|
276
|
-
margin: 10px 0 0;
|
|
277
|
-
color: #4b5563;
|
|
278
|
-
font-size: 15px;
|
|
279
|
-
font-weight: 500;
|
|
280
|
-
line-height: 1.45;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
.paywall-wallet-email-prompt label {
|
|
284
|
-
display: flex;
|
|
285
|
-
flex-direction: column;
|
|
286
|
-
gap: 8px;
|
|
287
|
-
margin-top: 18px;
|
|
288
|
-
color: #374151;
|
|
289
|
-
font-size: 13px;
|
|
290
|
-
font-weight: 700;
|
|
291
|
-
line-height: 1.2;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
.paywall-wallet-email-prompt input {
|
|
295
|
-
min-height: 48px;
|
|
296
|
-
border: 1px solid #d8deea;
|
|
297
|
-
border-radius: 12px;
|
|
298
|
-
padding: 0 14px;
|
|
299
|
-
color: #111827;
|
|
300
|
-
font: inherit;
|
|
301
|
-
font-size: 16px;
|
|
302
|
-
font-weight: 500;
|
|
303
|
-
outline: none;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
.paywall-wallet-email-prompt input:focus {
|
|
307
|
-
border-color: var(--color-secondary-text);
|
|
308
|
-
box-shadow: 0 0 0 3px rgb(63 81 181 / 12%);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
.paywall-wallet-email-prompt-error {
|
|
312
|
-
color: #c03232 !important;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
.paywall-wallet-email-prompt-actions {
|
|
316
|
-
display: grid;
|
|
317
|
-
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
318
|
-
gap: 10px;
|
|
319
|
-
margin-top: 18px;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
.paywall-wallet-email-prompt-actions button {
|
|
323
|
-
min-height: 48px;
|
|
324
|
-
border-radius: 14px;
|
|
325
|
-
border: 0;
|
|
326
|
-
font-size: 15px;
|
|
327
|
-
font-weight: 800;
|
|
328
|
-
cursor: pointer;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
.paywall-wallet-email-prompt-actions button[type='button'] {
|
|
332
|
-
background: #f2f5fb;
|
|
333
|
-
color: #4b5563;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
.paywall-wallet-email-prompt-actions button[type='submit'] {
|
|
337
|
-
background: var(--color-secondary-text);
|
|
338
|
-
color: #fff;
|
|
339
|
-
}
|
|
340
|
-
`;
|