@b3dotfun/sdk 0.1.68-alpha.2 → 0.1.68-alpha.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/dist/cjs/anyspend/react/components/checkout/AnySpendCheckout.d.ts +10 -6
- package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckout.js +55 -8
- package/dist/cjs/anyspend/react/components/checkout/VariablePricingInput.d.ts +17 -0
- package/dist/cjs/anyspend/react/components/checkout/VariablePricingInput.js +145 -0
- package/dist/cjs/anyspend/react/components/index.d.ts +1 -1
- package/dist/esm/anyspend/react/components/checkout/AnySpendCheckout.d.ts +10 -6
- package/dist/esm/anyspend/react/components/checkout/AnySpendCheckout.js +55 -8
- package/dist/esm/anyspend/react/components/checkout/VariablePricingInput.d.ts +17 -0
- package/dist/esm/anyspend/react/components/checkout/VariablePricingInput.js +142 -0
- package/dist/esm/anyspend/react/components/index.d.ts +1 -1
- package/dist/styles/index.css +1 -1
- package/dist/types/anyspend/react/components/checkout/AnySpendCheckout.d.ts +10 -6
- package/dist/types/anyspend/react/components/checkout/VariablePricingInput.d.ts +17 -0
- package/dist/types/anyspend/react/components/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/anyspend/docs/checkout-sessions.md +20 -3
- package/src/anyspend/react/components/checkout/AnySpendCheckout.tsx +73 -18
- package/src/anyspend/react/components/checkout/VariablePricingInput.tsx +247 -0
- package/src/anyspend/react/components/index.ts +1 -0
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
import {
|
|
3
|
-
export type { AnySpendCheckoutClasses } from "../types/classes";
|
|
2
|
+
import type { AddressData, CheckoutFormComponentProps, CheckoutFormSchema, DiscountResult, ShippingOption } from "../../../types/forms";
|
|
4
3
|
import type { AnySpendCheckoutClasses } from "../types/classes";
|
|
5
4
|
import type { AnySpendContent, AnySpendSlots, AnySpendTheme } from "../types/customization";
|
|
6
|
-
import
|
|
7
|
-
|
|
5
|
+
import { type PaymentMethod } from "./CheckoutPaymentPanel";
|
|
6
|
+
import { type VariablePricingConfig } from "./VariablePricingInput";
|
|
7
|
+
export type { AnySpendCheckoutClasses } from "../types/classes";
|
|
8
|
+
export type { VariablePricingConfig } from "./VariablePricingInput";
|
|
9
|
+
export type { AddressData, CheckoutFormComponentProps, CheckoutFormSchema, DiscountResult, ShippingOption };
|
|
8
10
|
export interface CheckoutItem {
|
|
9
11
|
id?: string;
|
|
10
12
|
name: string;
|
|
@@ -33,7 +35,7 @@ export interface AnySpendCheckoutProps {
|
|
|
33
35
|
destinationTokenAddress: string;
|
|
34
36
|
/** The destination chain ID */
|
|
35
37
|
destinationTokenChainId: number;
|
|
36
|
-
/** Line items */
|
|
38
|
+
/** Line items. When `variablePricing.enabled` is true, pass a single placeholder item (e.g. amount "0") — the user-entered amount overrides the total. */
|
|
37
39
|
items: CheckoutItem[];
|
|
38
40
|
/** Override computed total */
|
|
39
41
|
totalAmount?: string;
|
|
@@ -113,7 +115,9 @@ export interface AnySpendCheckoutProps {
|
|
|
113
115
|
onDiscountApplied?: (result: DiscountResult) => void;
|
|
114
116
|
/** Async function to validate a discount code. Returns DiscountResult. */
|
|
115
117
|
validateDiscount?: (code: string) => Promise<DiscountResult>;
|
|
118
|
+
/** Variable pricing / name your price config. When enabled, user enters amount before payment. */
|
|
119
|
+
variablePricing?: VariablePricingConfig;
|
|
116
120
|
/** When true, fees are added on top of the amount (payer pays more, receiver gets exact amount) */
|
|
117
121
|
feeOnTop?: boolean;
|
|
118
122
|
}
|
|
119
|
-
export declare function AnySpendCheckout({ mode, recipientAddress, destinationTokenAddress, destinationTokenChainId, items, totalAmount: totalAmountOverride, organizationName, organizationLogo, themeColor, buttonText, checkoutSessionId, onSuccess, onError, returnUrl, returnLabel, classes, footer, defaultPaymentMethod, senderAddress, slots, content, theme, showPoints, showOrderId, shipping: shippingProp, tax, discount: discountProp, summaryLines, formSchema, formComponent, onFormSubmit, shippingOptions, collectShippingAddress, onShippingChange: onShippingChangeProp, enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount, feeOnTop, }: AnySpendCheckoutProps): import("react/jsx-runtime").JSX.Element;
|
|
123
|
+
export declare function AnySpendCheckout({ mode, recipientAddress, destinationTokenAddress, destinationTokenChainId, items, totalAmount: totalAmountOverride, organizationName, organizationLogo, themeColor, buttonText, checkoutSessionId, onSuccess, onError, returnUrl, returnLabel, classes, footer, defaultPaymentMethod, senderAddress, slots, content, theme, showPoints, showOrderId, shipping: shippingProp, tax, discount: discountProp, summaryLines, formSchema, formComponent, onFormSubmit, shippingOptions, collectShippingAddress, onShippingChange: onShippingChangeProp, enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount, variablePricing, feeOnTop, }: AnySpendCheckoutProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -3,17 +3,18 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.AnySpendCheckout = AnySpendCheckout;
|
|
5
5
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
-
const react_1 = require("../../../../global-account/react");
|
|
7
6
|
const constants_1 = require("../../../../anyspend/constants");
|
|
7
|
+
const react_1 = require("../../../../global-account/react");
|
|
8
8
|
const number_1 = require("../../../../shared/utils/number");
|
|
9
9
|
const react_2 = require("react");
|
|
10
10
|
const useAnyspendQuote_1 = require("../../hooks/useAnyspendQuote");
|
|
11
11
|
const AnySpendFingerprintWrapper_1 = require("../AnySpendFingerprintWrapper");
|
|
12
|
+
const AnySpendCustomizationContext_1 = require("../context/AnySpendCustomizationContext");
|
|
12
13
|
const CheckoutCartPanel_1 = require("./CheckoutCartPanel");
|
|
13
14
|
const CheckoutFormPanel_1 = require("./CheckoutFormPanel");
|
|
14
15
|
const CheckoutLayout_1 = require("./CheckoutLayout");
|
|
15
16
|
const CheckoutPaymentPanel_1 = require("./CheckoutPaymentPanel");
|
|
16
|
-
const
|
|
17
|
+
const VariablePricingInput_1 = require("./VariablePricingInput");
|
|
17
18
|
const emptyAddress = { street: "", city: "", state: "", zip: "", country: "" };
|
|
18
19
|
function AnySpendCheckout({ mode = "page", recipientAddress, destinationTokenAddress, destinationTokenChainId, items, totalAmount: totalAmountOverride, organizationName, organizationLogo, themeColor, buttonText = "Pay", checkoutSessionId, onSuccess, onError, returnUrl, returnLabel, classes, footer, defaultPaymentMethod, senderAddress, slots, content, theme, showPoints, showOrderId, shipping: shippingProp, tax, discount: discountProp, summaryLines,
|
|
19
20
|
// New form props
|
|
@@ -21,7 +22,13 @@ formSchema, formComponent, onFormSubmit,
|
|
|
21
22
|
// New shipping props
|
|
22
23
|
shippingOptions, collectShippingAddress, onShippingChange: onShippingChangeProp,
|
|
23
24
|
// New discount props
|
|
24
|
-
enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount,
|
|
25
|
+
enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount,
|
|
26
|
+
// Variable pricing
|
|
27
|
+
variablePricing, feeOnTop, }) {
|
|
28
|
+
// ===== Variable pricing state =====
|
|
29
|
+
const [variablePricingAmount, setVariablePricingAmount] = (0, react_2.useState)("0");
|
|
30
|
+
const isVariablePricingActive = variablePricing?.enabled === true;
|
|
31
|
+
const isVariablePricingValid = isVariablePricingActive ? variablePricingAmount !== "0" : true;
|
|
25
32
|
// ===== Form state =====
|
|
26
33
|
const [formData, setFormData] = (0, react_2.useState)({});
|
|
27
34
|
const [selectedShipping, setSelectedShipping] = (0, react_2.useState)(null);
|
|
@@ -66,7 +73,25 @@ enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount,
|
|
|
66
73
|
return undefined;
|
|
67
74
|
}, [appliedDiscount, discountProp]);
|
|
68
75
|
// Compute total from items + adjustments (including dynamic shipping/discount)
|
|
76
|
+
// Variable pricing overrides the total when active
|
|
69
77
|
const computedTotal = (0, react_2.useMemo)(() => {
|
|
78
|
+
if (isVariablePricingActive && variablePricingAmount !== "0") {
|
|
79
|
+
let total = (0, number_1.safeBigInt)(variablePricingAmount);
|
|
80
|
+
if (effectiveShipping?.amount)
|
|
81
|
+
total += (0, number_1.safeBigInt)(effectiveShipping.amount);
|
|
82
|
+
const taxAmt = typeof tax === "string" ? tax : tax?.amount;
|
|
83
|
+
if (taxAmt)
|
|
84
|
+
total += (0, number_1.safeBigInt)(taxAmt);
|
|
85
|
+
if (effectiveDiscount?.amount)
|
|
86
|
+
total -= (0, number_1.safeBigInt)(effectiveDiscount.amount);
|
|
87
|
+
if (summaryLines) {
|
|
88
|
+
for (const line of summaryLines)
|
|
89
|
+
total += (0, number_1.safeBigInt)(line.amount);
|
|
90
|
+
}
|
|
91
|
+
if (total < BigInt(0))
|
|
92
|
+
total = BigInt(0);
|
|
93
|
+
return total.toString();
|
|
94
|
+
}
|
|
70
95
|
if (totalAmountOverride)
|
|
71
96
|
return totalAmountOverride;
|
|
72
97
|
let total = BigInt(0);
|
|
@@ -87,7 +112,16 @@ enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount,
|
|
|
87
112
|
if (total < BigInt(0))
|
|
88
113
|
total = BigInt(0);
|
|
89
114
|
return total.toString();
|
|
90
|
-
}, [
|
|
115
|
+
}, [
|
|
116
|
+
items,
|
|
117
|
+
totalAmountOverride,
|
|
118
|
+
effectiveShipping,
|
|
119
|
+
tax,
|
|
120
|
+
effectiveDiscount,
|
|
121
|
+
summaryLines,
|
|
122
|
+
isVariablePricingActive,
|
|
123
|
+
variablePricingAmount,
|
|
124
|
+
]);
|
|
91
125
|
// Get destination token metadata
|
|
92
126
|
const { data: tokenData } = (0, react_1.useTokenData)(destinationTokenChainId, destinationTokenAddress);
|
|
93
127
|
const tokenSymbol = tokenData?.symbol || "";
|
|
@@ -139,14 +173,27 @@ enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount,
|
|
|
139
173
|
meta.customerName = formData.name;
|
|
140
174
|
if (checkoutSessionId)
|
|
141
175
|
meta.checkoutSessionId = checkoutSessionId;
|
|
176
|
+
if (isVariablePricingActive && variablePricingAmount !== "0") {
|
|
177
|
+
meta.variablePricingAmount = variablePricingAmount;
|
|
178
|
+
}
|
|
142
179
|
return Object.keys(meta).length > 0 ? meta : undefined;
|
|
143
|
-
}, [
|
|
144
|
-
|
|
180
|
+
}, [
|
|
181
|
+
formData,
|
|
182
|
+
selectedShipping,
|
|
183
|
+
shippingAddress,
|
|
184
|
+
appliedDiscount,
|
|
185
|
+
checkoutSessionId,
|
|
186
|
+
isVariablePricingActive,
|
|
187
|
+
variablePricingAmount,
|
|
188
|
+
]);
|
|
189
|
+
// Check if required form fields are filled and variable pricing is valid
|
|
145
190
|
const isFormValid = (0, react_2.useMemo)(() => {
|
|
191
|
+
if (!isVariablePricingValid)
|
|
192
|
+
return false;
|
|
146
193
|
if (!formSchema)
|
|
147
194
|
return true;
|
|
148
195
|
return formSchema.fields.filter(f => f.required).every(f => formData[f.id] != null && formData[f.id] !== "");
|
|
149
|
-
}, [formSchema, formData]);
|
|
196
|
+
}, [formSchema, formData, isVariablePricingValid]);
|
|
150
197
|
// Check if we have a form panel to show
|
|
151
198
|
const hasFormContent = (formSchema && formSchema.fields.length > 0) ||
|
|
152
199
|
formComponent ||
|
|
@@ -154,5 +201,5 @@ enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount,
|
|
|
154
201
|
(shippingOptions && shippingOptions.length > 0) ||
|
|
155
202
|
collectShippingAddress ||
|
|
156
203
|
enableDiscountCode;
|
|
157
|
-
return ((0, jsx_runtime_1.jsx)(AnySpendFingerprintWrapper_1.AnySpendFingerprintWrapper, { fingerprint: fingerprint, children: (0, jsx_runtime_1.jsx)(AnySpendCustomizationContext_1.AnySpendCustomizationProvider, { slots: slots, content: content, theme: theme, children: (0, jsx_runtime_1.jsx)(CheckoutLayout_1.CheckoutLayout, { mode: mode, paymentPanel: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [hasFormContent && ((0, jsx_runtime_1.jsxs)("div", { className: "mb-6", children: [(0, jsx_runtime_1.jsx)(CheckoutFormPanel_1.CheckoutFormPanel, { formSchema: formSchema, formComponent: formComponent, shippingOptions: shippingOptions, collectShippingAddress: collectShippingAddress, enableDiscountCode: enableDiscountCode, validateDiscount: validateDiscount, tokenSymbol: tokenSymbol, tokenDecimals: tokenDecimals, classes: classes, formData: formData, onFormDataChange: handleFormDataChange, selectedShipping: selectedShipping, onShippingChange: handleShippingChange, appliedDiscount: appliedDiscount, onDiscountApplied: handleDiscountApplied, onDiscountRemoved: handleDiscountRemoved, shippingAddress: shippingAddress, onShippingAddressChange: setShippingAddress, checkoutFormSlot: slots?.checkoutForm }), (0, jsx_runtime_1.jsx)("div", { className: "mt-6 border-t border-gray-200 dark:border-neutral-700" })] })), (0, jsx_runtime_1.jsx)(CheckoutPaymentPanel_1.CheckoutPaymentPanel, { recipientAddress: recipientAddress, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, totalAmount: computedTotal, buttonText: buttonText, themeColor: themeColor, returnUrl: returnUrl, returnLabel: returnLabel, onSuccess: onSuccess, onError: onError, classes: classes, defaultPaymentMethod: defaultPaymentMethod, senderAddress: senderAddress, showPoints: showPoints, showOrderId: showOrderId, callbackMetadata: checkoutFormMetadata, isFormValid: isFormValid, feeOnTop: feeOnTop })] }), cartPanel: (0, jsx_runtime_1.jsx)(CheckoutCartPanel_1.CheckoutCartPanel, { items: items, totalAmount: computedTotal, tokenSymbol: tokenSymbol, tokenDecimals: tokenDecimals, organizationName: organizationName, organizationLogo: organizationLogo, classes: classes, footer: footer, shipping: effectiveShipping, tax: typeof tax === "string" ? { amount: tax } : tax, discount: effectiveDiscount, summaryLines: summaryLines, usdEquivalent: usdEquivalent }), classes: classes }) }) }));
|
|
204
|
+
return ((0, jsx_runtime_1.jsx)(AnySpendFingerprintWrapper_1.AnySpendFingerprintWrapper, { fingerprint: fingerprint, children: (0, jsx_runtime_1.jsx)(AnySpendCustomizationContext_1.AnySpendCustomizationProvider, { slots: slots, content: content, theme: theme, children: (0, jsx_runtime_1.jsx)(CheckoutLayout_1.CheckoutLayout, { mode: mode, paymentPanel: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [isVariablePricingActive && tokenData && variablePricing && ((0, jsx_runtime_1.jsx)(VariablePricingInput_1.VariablePricingInput, { config: variablePricing, tokenDecimals: tokenDecimals, tokenSymbol: tokenSymbol, themeColor: themeColor, onChange: setVariablePricingAmount })), hasFormContent && ((0, jsx_runtime_1.jsxs)("div", { className: "mb-6", children: [(0, jsx_runtime_1.jsx)(CheckoutFormPanel_1.CheckoutFormPanel, { formSchema: formSchema, formComponent: formComponent, shippingOptions: shippingOptions, collectShippingAddress: collectShippingAddress, enableDiscountCode: enableDiscountCode, validateDiscount: validateDiscount, tokenSymbol: tokenSymbol, tokenDecimals: tokenDecimals, classes: classes, formData: formData, onFormDataChange: handleFormDataChange, selectedShipping: selectedShipping, onShippingChange: handleShippingChange, appliedDiscount: appliedDiscount, onDiscountApplied: handleDiscountApplied, onDiscountRemoved: handleDiscountRemoved, shippingAddress: shippingAddress, onShippingAddressChange: setShippingAddress, checkoutFormSlot: slots?.checkoutForm }), (0, jsx_runtime_1.jsx)("div", { className: "mt-6 border-t border-gray-200 dark:border-neutral-700" })] })), (0, jsx_runtime_1.jsx)(CheckoutPaymentPanel_1.CheckoutPaymentPanel, { recipientAddress: recipientAddress, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, totalAmount: computedTotal, buttonText: buttonText, themeColor: themeColor, returnUrl: returnUrl, returnLabel: returnLabel, onSuccess: onSuccess, onError: onError, classes: classes, defaultPaymentMethod: defaultPaymentMethod, senderAddress: senderAddress, showPoints: showPoints, showOrderId: showOrderId, callbackMetadata: checkoutFormMetadata, isFormValid: isFormValid, feeOnTop: feeOnTop })] }), cartPanel: (0, jsx_runtime_1.jsx)(CheckoutCartPanel_1.CheckoutCartPanel, { items: items, totalAmount: computedTotal, tokenSymbol: tokenSymbol, tokenDecimals: tokenDecimals, organizationName: organizationName, organizationLogo: organizationLogo, classes: classes, footer: footer, shipping: effectiveShipping, tax: typeof tax === "string" ? { amount: tax } : tax, discount: effectiveDiscount, summaryLines: summaryLines, usdEquivalent: usdEquivalent }), classes: classes }) }) }));
|
|
158
205
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface VariablePricingConfig {
|
|
2
|
+
enabled: boolean;
|
|
3
|
+
minAmount?: string;
|
|
4
|
+
maxAmount?: string;
|
|
5
|
+
suggestedAmount?: string;
|
|
6
|
+
label?: string;
|
|
7
|
+
currency?: string;
|
|
8
|
+
}
|
|
9
|
+
interface VariablePricingInputProps {
|
|
10
|
+
config: VariablePricingConfig;
|
|
11
|
+
tokenDecimals: number;
|
|
12
|
+
tokenSymbol: string;
|
|
13
|
+
themeColor?: string;
|
|
14
|
+
onChange: (amountWei: string) => void;
|
|
15
|
+
}
|
|
16
|
+
export declare function VariablePricingInput({ config, tokenDecimals, tokenSymbol, themeColor, onChange, }: VariablePricingInputProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.VariablePricingInput = VariablePricingInput;
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const cn_1 = require("../../../../shared/utils/cn");
|
|
7
|
+
const number_1 = require("../../../../shared/utils/number");
|
|
8
|
+
const react_1 = require("motion/react");
|
|
9
|
+
const react_2 = require("react");
|
|
10
|
+
function VariablePricingInput({ config, tokenDecimals, tokenSymbol, themeColor, onChange, }) {
|
|
11
|
+
const currency = config.currency || tokenSymbol;
|
|
12
|
+
// Convert suggested amount from wei to display
|
|
13
|
+
const initialValue = (0, react_2.useMemo)(() => {
|
|
14
|
+
if (config.suggestedAmount) {
|
|
15
|
+
try {
|
|
16
|
+
return (0, number_1.formatUnits)(config.suggestedAmount, tokenDecimals);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return "";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return "";
|
|
23
|
+
}, [config.suggestedAmount, tokenDecimals]);
|
|
24
|
+
const [displayValue, setDisplayValue] = (0, react_2.useState)(initialValue);
|
|
25
|
+
const [error, setError] = (0, react_2.useState)(null);
|
|
26
|
+
// Min/max in display units
|
|
27
|
+
const minDisplay = (0, react_2.useMemo)(() => {
|
|
28
|
+
if (!config.minAmount)
|
|
29
|
+
return null;
|
|
30
|
+
try {
|
|
31
|
+
return parseFloat((0, number_1.formatUnits)(config.minAmount, tokenDecimals));
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}, [config.minAmount, tokenDecimals]);
|
|
37
|
+
const maxDisplay = (0, react_2.useMemo)(() => {
|
|
38
|
+
if (!config.maxAmount)
|
|
39
|
+
return null;
|
|
40
|
+
try {
|
|
41
|
+
return parseFloat((0, number_1.formatUnits)(config.maxAmount, tokenDecimals));
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}, [config.maxAmount, tokenDecimals]);
|
|
47
|
+
// Preset amounts
|
|
48
|
+
const presetAmounts = (0, react_2.useMemo)(() => {
|
|
49
|
+
const presets = [];
|
|
50
|
+
if (config.suggestedAmount) {
|
|
51
|
+
try {
|
|
52
|
+
const suggested = parseFloat((0, number_1.formatUnits)(config.suggestedAmount, tokenDecimals));
|
|
53
|
+
const candidates = [suggested / 2, suggested, suggested * 2];
|
|
54
|
+
for (const val of candidates) {
|
|
55
|
+
if (val <= 0)
|
|
56
|
+
continue;
|
|
57
|
+
if (minDisplay !== null && val < minDisplay)
|
|
58
|
+
continue;
|
|
59
|
+
if (maxDisplay !== null && val > maxDisplay)
|
|
60
|
+
continue;
|
|
61
|
+
const display = val % 1 === 0 ? val.toString() : val.toFixed(2);
|
|
62
|
+
presets.push({ label: `${display}`, value: display });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// skip presets
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return presets;
|
|
70
|
+
}, [config.suggestedAmount, tokenDecimals, minDisplay, maxDisplay]);
|
|
71
|
+
const validate = (0, react_2.useCallback)((value) => {
|
|
72
|
+
const parsed = parseFloat(value);
|
|
73
|
+
if (!value || isNaN(parsed))
|
|
74
|
+
return "Please enter a valid number";
|
|
75
|
+
if (parsed <= 0)
|
|
76
|
+
return "Please enter an amount";
|
|
77
|
+
if (minDisplay !== null && parsed < minDisplay) {
|
|
78
|
+
const display = minDisplay % 1 === 0 ? minDisplay.toString() : minDisplay.toFixed(2);
|
|
79
|
+
return `Minimum amount is ${display} ${currency}`;
|
|
80
|
+
}
|
|
81
|
+
if (maxDisplay !== null && parsed > maxDisplay) {
|
|
82
|
+
const display = maxDisplay % 1 === 0 ? maxDisplay.toString() : maxDisplay.toFixed(2);
|
|
83
|
+
return `Maximum amount is ${display} ${currency}`;
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}, [minDisplay, maxDisplay, currency]);
|
|
87
|
+
const convertToWei = (0, react_2.useCallback)((value) => {
|
|
88
|
+
try {
|
|
89
|
+
const [whole, frac = ""] = value.split(".");
|
|
90
|
+
const paddedFrac = frac.padEnd(tokenDecimals, "0").slice(0, tokenDecimals);
|
|
91
|
+
const factor = BigInt(10) ** BigInt(tokenDecimals);
|
|
92
|
+
return (BigInt(whole || "0") * factor + BigInt(paddedFrac)).toString();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return "0";
|
|
96
|
+
}
|
|
97
|
+
}, [tokenDecimals]);
|
|
98
|
+
const handleChange = (0, react_2.useCallback)((value) => {
|
|
99
|
+
setDisplayValue(value);
|
|
100
|
+
const validationError = validate(value);
|
|
101
|
+
setError(validationError);
|
|
102
|
+
if (!validationError && value && parseFloat(value) > 0) {
|
|
103
|
+
onChange(convertToWei(value));
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
onChange("0");
|
|
107
|
+
}
|
|
108
|
+
}, [validate, convertToWei, onChange]);
|
|
109
|
+
const handlePresetClick = (0, react_2.useCallback)((value) => {
|
|
110
|
+
setDisplayValue(value);
|
|
111
|
+
setError(null);
|
|
112
|
+
onChange(convertToWei(value));
|
|
113
|
+
}, [convertToWei, onChange]);
|
|
114
|
+
// Notify parent with initial value on mount
|
|
115
|
+
(0, react_2.useEffect)(() => {
|
|
116
|
+
if (initialValue && !validate(initialValue)) {
|
|
117
|
+
onChange(convertToWei(initialValue));
|
|
118
|
+
}
|
|
119
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
120
|
+
}, []);
|
|
121
|
+
const formatHint = () => {
|
|
122
|
+
if (minDisplay !== null && maxDisplay !== null) {
|
|
123
|
+
const minStr = minDisplay % 1 === 0 ? minDisplay.toString() : minDisplay.toFixed(2);
|
|
124
|
+
const maxStr = maxDisplay % 1 === 0 ? maxDisplay.toString() : maxDisplay.toFixed(2);
|
|
125
|
+
return `${minStr} – ${maxStr} ${currency}`;
|
|
126
|
+
}
|
|
127
|
+
if (minDisplay !== null) {
|
|
128
|
+
const minStr = minDisplay % 1 === 0 ? minDisplay.toString() : minDisplay.toFixed(2);
|
|
129
|
+
return `Min: ${minStr} ${currency}`;
|
|
130
|
+
}
|
|
131
|
+
if (maxDisplay !== null) {
|
|
132
|
+
const maxStr = maxDisplay % 1 === 0 ? maxDisplay.toString() : maxDisplay.toFixed(2);
|
|
133
|
+
return `Max: ${maxStr} ${currency}`;
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
};
|
|
137
|
+
const hint = formatHint();
|
|
138
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "anyspend-variable-pricing mb-6", children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "variable-pricing-amount", className: "mb-3 block text-lg font-semibold text-gray-900 dark:text-gray-100", children: config.label || "Enter amount" }), presetAmounts.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "mb-3 flex flex-wrap gap-2", children: presetAmounts.map(preset => ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => handlePresetClick(preset.value), className: (0, cn_1.cn)("rounded-full border px-4 py-2 text-sm font-medium transition-colors", displayValue === preset.value
|
|
139
|
+
? "border-transparent text-white"
|
|
140
|
+
: "border-gray-200 text-gray-700 hover:bg-gray-50 dark:border-neutral-600 dark:text-gray-300 dark:hover:bg-neutral-800"), style: displayValue === preset.value ? { backgroundColor: themeColor || "hsl(var(--as-brand))" } : undefined, children: [preset.label, " ", currency] }, preset.value))) })), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)("input", { id: "variable-pricing-amount", type: "text", inputMode: "decimal", value: displayValue, onChange: e => {
|
|
141
|
+
// Normalize comma decimal separators for locale compatibility
|
|
142
|
+
const normalized = e.target.value.replace(",", ".");
|
|
143
|
+
handleChange(normalized);
|
|
144
|
+
}, className: "w-full rounded-xl border border-gray-200 bg-gray-50 px-4 py-3.5 pr-16 text-lg font-semibold text-gray-900 placeholder:text-gray-300 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500/20 dark:border-neutral-600 dark:bg-neutral-800 dark:text-gray-100 dark:placeholder:text-neutral-600 dark:focus:border-blue-400", placeholder: "0.00" }), (0, jsx_runtime_1.jsx)("span", { className: "absolute right-4 top-1/2 -translate-y-1/2 text-sm font-medium text-gray-400 dark:text-gray-500", children: currency })] }), hint && (0, jsx_runtime_1.jsx)("p", { className: "mt-1.5 text-xs text-gray-500 dark:text-gray-400", children: hint }), (0, jsx_runtime_1.jsx)(react_1.AnimatePresence, { initial: false, children: error && ((0, jsx_runtime_1.jsx)(react_1.motion.p, { initial: { opacity: 0, height: 0 }, animate: { opacity: 1, height: "auto" }, exit: { opacity: 0, height: 0 }, transition: { duration: 0.15, ease: "easeOut" }, className: "mt-1.5 text-sm text-red-500", children: error }, "variable-price-error")) })] }));
|
|
145
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { AnySpendCheckout } from "./checkout/AnySpendCheckout";
|
|
2
|
-
export type { AnySpendCheckoutProps, CheckoutItem, CheckoutSummaryLine, AnySpendCheckoutClasses, CheckoutFormSchema, CheckoutFormComponentProps, ShippingOption, DiscountResult, AddressData, } from "./checkout/AnySpendCheckout";
|
|
2
|
+
export type { AnySpendCheckoutProps, CheckoutItem, CheckoutSummaryLine, AnySpendCheckoutClasses, CheckoutFormSchema, CheckoutFormComponentProps, ShippingOption, DiscountResult, AddressData, VariablePricingConfig, } from "./checkout/AnySpendCheckout";
|
|
3
3
|
export { AnySpendCheckoutTrigger } from "./checkout/AnySpendCheckoutTrigger";
|
|
4
4
|
export type { AnySpendCheckoutTriggerProps } from "./checkout/AnySpendCheckoutTrigger";
|
|
5
5
|
export type { PaymentMethod } from "./checkout/CheckoutPaymentPanel";
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
import {
|
|
3
|
-
export type { AnySpendCheckoutClasses } from "../types/classes";
|
|
2
|
+
import type { AddressData, CheckoutFormComponentProps, CheckoutFormSchema, DiscountResult, ShippingOption } from "../../../types/forms";
|
|
4
3
|
import type { AnySpendCheckoutClasses } from "../types/classes";
|
|
5
4
|
import type { AnySpendContent, AnySpendSlots, AnySpendTheme } from "../types/customization";
|
|
6
|
-
import
|
|
7
|
-
|
|
5
|
+
import { type PaymentMethod } from "./CheckoutPaymentPanel";
|
|
6
|
+
import { type VariablePricingConfig } from "./VariablePricingInput";
|
|
7
|
+
export type { AnySpendCheckoutClasses } from "../types/classes";
|
|
8
|
+
export type { VariablePricingConfig } from "./VariablePricingInput";
|
|
9
|
+
export type { AddressData, CheckoutFormComponentProps, CheckoutFormSchema, DiscountResult, ShippingOption };
|
|
8
10
|
export interface CheckoutItem {
|
|
9
11
|
id?: string;
|
|
10
12
|
name: string;
|
|
@@ -33,7 +35,7 @@ export interface AnySpendCheckoutProps {
|
|
|
33
35
|
destinationTokenAddress: string;
|
|
34
36
|
/** The destination chain ID */
|
|
35
37
|
destinationTokenChainId: number;
|
|
36
|
-
/** Line items */
|
|
38
|
+
/** Line items. When `variablePricing.enabled` is true, pass a single placeholder item (e.g. amount "0") — the user-entered amount overrides the total. */
|
|
37
39
|
items: CheckoutItem[];
|
|
38
40
|
/** Override computed total */
|
|
39
41
|
totalAmount?: string;
|
|
@@ -113,7 +115,9 @@ export interface AnySpendCheckoutProps {
|
|
|
113
115
|
onDiscountApplied?: (result: DiscountResult) => void;
|
|
114
116
|
/** Async function to validate a discount code. Returns DiscountResult. */
|
|
115
117
|
validateDiscount?: (code: string) => Promise<DiscountResult>;
|
|
118
|
+
/** Variable pricing / name your price config. When enabled, user enters amount before payment. */
|
|
119
|
+
variablePricing?: VariablePricingConfig;
|
|
116
120
|
/** When true, fees are added on top of the amount (payer pays more, receiver gets exact amount) */
|
|
117
121
|
feeOnTop?: boolean;
|
|
118
122
|
}
|
|
119
|
-
export declare function AnySpendCheckout({ mode, recipientAddress, destinationTokenAddress, destinationTokenChainId, items, totalAmount: totalAmountOverride, organizationName, organizationLogo, themeColor, buttonText, checkoutSessionId, onSuccess, onError, returnUrl, returnLabel, classes, footer, defaultPaymentMethod, senderAddress, slots, content, theme, showPoints, showOrderId, shipping: shippingProp, tax, discount: discountProp, summaryLines, formSchema, formComponent, onFormSubmit, shippingOptions, collectShippingAddress, onShippingChange: onShippingChangeProp, enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount, feeOnTop, }: AnySpendCheckoutProps): import("react/jsx-runtime").JSX.Element;
|
|
123
|
+
export declare function AnySpendCheckout({ mode, recipientAddress, destinationTokenAddress, destinationTokenChainId, items, totalAmount: totalAmountOverride, organizationName, organizationLogo, themeColor, buttonText, checkoutSessionId, onSuccess, onError, returnUrl, returnLabel, classes, footer, defaultPaymentMethod, senderAddress, slots, content, theme, showPoints, showOrderId, shipping: shippingProp, tax, discount: discountProp, summaryLines, formSchema, formComponent, onFormSubmit, shippingOptions, collectShippingAddress, onShippingChange: onShippingChangeProp, enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount, variablePricing, feeOnTop, }: AnySpendCheckoutProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useTokenData } from "../../../../global-account/react/index.js";
|
|
4
3
|
import { USDC_BASE } from "../../../../anyspend/constants/index.js";
|
|
4
|
+
import { useTokenData } from "../../../../global-account/react/index.js";
|
|
5
5
|
import { formatUnits, safeBigInt } from "../../../../shared/utils/number.js";
|
|
6
6
|
import { useCallback, useMemo, useState } from "react";
|
|
7
7
|
import { useAnyspendQuote } from "../../hooks/useAnyspendQuote.js";
|
|
8
8
|
import { AnySpendFingerprintWrapper, getFingerprintConfig } from "../AnySpendFingerprintWrapper.js";
|
|
9
|
+
import { AnySpendCustomizationProvider } from "../context/AnySpendCustomizationContext.js";
|
|
9
10
|
import { CheckoutCartPanel } from "./CheckoutCartPanel.js";
|
|
10
11
|
import { CheckoutFormPanel } from "./CheckoutFormPanel.js";
|
|
11
12
|
import { CheckoutLayout } from "./CheckoutLayout.js";
|
|
12
13
|
import { CheckoutPaymentPanel } from "./CheckoutPaymentPanel.js";
|
|
13
|
-
import {
|
|
14
|
+
import { VariablePricingInput } from "./VariablePricingInput.js";
|
|
14
15
|
const emptyAddress = { street: "", city: "", state: "", zip: "", country: "" };
|
|
15
16
|
export function AnySpendCheckout({ mode = "page", recipientAddress, destinationTokenAddress, destinationTokenChainId, items, totalAmount: totalAmountOverride, organizationName, organizationLogo, themeColor, buttonText = "Pay", checkoutSessionId, onSuccess, onError, returnUrl, returnLabel, classes, footer, defaultPaymentMethod, senderAddress, slots, content, theme, showPoints, showOrderId, shipping: shippingProp, tax, discount: discountProp, summaryLines,
|
|
16
17
|
// New form props
|
|
@@ -18,7 +19,13 @@ formSchema, formComponent, onFormSubmit,
|
|
|
18
19
|
// New shipping props
|
|
19
20
|
shippingOptions, collectShippingAddress, onShippingChange: onShippingChangeProp,
|
|
20
21
|
// New discount props
|
|
21
|
-
enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount,
|
|
22
|
+
enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount,
|
|
23
|
+
// Variable pricing
|
|
24
|
+
variablePricing, feeOnTop, }) {
|
|
25
|
+
// ===== Variable pricing state =====
|
|
26
|
+
const [variablePricingAmount, setVariablePricingAmount] = useState("0");
|
|
27
|
+
const isVariablePricingActive = variablePricing?.enabled === true;
|
|
28
|
+
const isVariablePricingValid = isVariablePricingActive ? variablePricingAmount !== "0" : true;
|
|
22
29
|
// ===== Form state =====
|
|
23
30
|
const [formData, setFormData] = useState({});
|
|
24
31
|
const [selectedShipping, setSelectedShipping] = useState(null);
|
|
@@ -63,7 +70,25 @@ enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount,
|
|
|
63
70
|
return undefined;
|
|
64
71
|
}, [appliedDiscount, discountProp]);
|
|
65
72
|
// Compute total from items + adjustments (including dynamic shipping/discount)
|
|
73
|
+
// Variable pricing overrides the total when active
|
|
66
74
|
const computedTotal = useMemo(() => {
|
|
75
|
+
if (isVariablePricingActive && variablePricingAmount !== "0") {
|
|
76
|
+
let total = safeBigInt(variablePricingAmount);
|
|
77
|
+
if (effectiveShipping?.amount)
|
|
78
|
+
total += safeBigInt(effectiveShipping.amount);
|
|
79
|
+
const taxAmt = typeof tax === "string" ? tax : tax?.amount;
|
|
80
|
+
if (taxAmt)
|
|
81
|
+
total += safeBigInt(taxAmt);
|
|
82
|
+
if (effectiveDiscount?.amount)
|
|
83
|
+
total -= safeBigInt(effectiveDiscount.amount);
|
|
84
|
+
if (summaryLines) {
|
|
85
|
+
for (const line of summaryLines)
|
|
86
|
+
total += safeBigInt(line.amount);
|
|
87
|
+
}
|
|
88
|
+
if (total < BigInt(0))
|
|
89
|
+
total = BigInt(0);
|
|
90
|
+
return total.toString();
|
|
91
|
+
}
|
|
67
92
|
if (totalAmountOverride)
|
|
68
93
|
return totalAmountOverride;
|
|
69
94
|
let total = BigInt(0);
|
|
@@ -84,7 +109,16 @@ enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount,
|
|
|
84
109
|
if (total < BigInt(0))
|
|
85
110
|
total = BigInt(0);
|
|
86
111
|
return total.toString();
|
|
87
|
-
}, [
|
|
112
|
+
}, [
|
|
113
|
+
items,
|
|
114
|
+
totalAmountOverride,
|
|
115
|
+
effectiveShipping,
|
|
116
|
+
tax,
|
|
117
|
+
effectiveDiscount,
|
|
118
|
+
summaryLines,
|
|
119
|
+
isVariablePricingActive,
|
|
120
|
+
variablePricingAmount,
|
|
121
|
+
]);
|
|
88
122
|
// Get destination token metadata
|
|
89
123
|
const { data: tokenData } = useTokenData(destinationTokenChainId, destinationTokenAddress);
|
|
90
124
|
const tokenSymbol = tokenData?.symbol || "";
|
|
@@ -136,14 +170,27 @@ enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount,
|
|
|
136
170
|
meta.customerName = formData.name;
|
|
137
171
|
if (checkoutSessionId)
|
|
138
172
|
meta.checkoutSessionId = checkoutSessionId;
|
|
173
|
+
if (isVariablePricingActive && variablePricingAmount !== "0") {
|
|
174
|
+
meta.variablePricingAmount = variablePricingAmount;
|
|
175
|
+
}
|
|
139
176
|
return Object.keys(meta).length > 0 ? meta : undefined;
|
|
140
|
-
}, [
|
|
141
|
-
|
|
177
|
+
}, [
|
|
178
|
+
formData,
|
|
179
|
+
selectedShipping,
|
|
180
|
+
shippingAddress,
|
|
181
|
+
appliedDiscount,
|
|
182
|
+
checkoutSessionId,
|
|
183
|
+
isVariablePricingActive,
|
|
184
|
+
variablePricingAmount,
|
|
185
|
+
]);
|
|
186
|
+
// Check if required form fields are filled and variable pricing is valid
|
|
142
187
|
const isFormValid = useMemo(() => {
|
|
188
|
+
if (!isVariablePricingValid)
|
|
189
|
+
return false;
|
|
143
190
|
if (!formSchema)
|
|
144
191
|
return true;
|
|
145
192
|
return formSchema.fields.filter(f => f.required).every(f => formData[f.id] != null && formData[f.id] !== "");
|
|
146
|
-
}, [formSchema, formData]);
|
|
193
|
+
}, [formSchema, formData, isVariablePricingValid]);
|
|
147
194
|
// Check if we have a form panel to show
|
|
148
195
|
const hasFormContent = (formSchema && formSchema.fields.length > 0) ||
|
|
149
196
|
formComponent ||
|
|
@@ -151,5 +198,5 @@ enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount,
|
|
|
151
198
|
(shippingOptions && shippingOptions.length > 0) ||
|
|
152
199
|
collectShippingAddress ||
|
|
153
200
|
enableDiscountCode;
|
|
154
|
-
return (_jsx(AnySpendFingerprintWrapper, { fingerprint: fingerprint, children: _jsx(AnySpendCustomizationProvider, { slots: slots, content: content, theme: theme, children: _jsx(CheckoutLayout, { mode: mode, paymentPanel: _jsxs(_Fragment, { children: [hasFormContent && (_jsxs("div", { className: "mb-6", children: [_jsx(CheckoutFormPanel, { formSchema: formSchema, formComponent: formComponent, shippingOptions: shippingOptions, collectShippingAddress: collectShippingAddress, enableDiscountCode: enableDiscountCode, validateDiscount: validateDiscount, tokenSymbol: tokenSymbol, tokenDecimals: tokenDecimals, classes: classes, formData: formData, onFormDataChange: handleFormDataChange, selectedShipping: selectedShipping, onShippingChange: handleShippingChange, appliedDiscount: appliedDiscount, onDiscountApplied: handleDiscountApplied, onDiscountRemoved: handleDiscountRemoved, shippingAddress: shippingAddress, onShippingAddressChange: setShippingAddress, checkoutFormSlot: slots?.checkoutForm }), _jsx("div", { className: "mt-6 border-t border-gray-200 dark:border-neutral-700" })] })), _jsx(CheckoutPaymentPanel, { recipientAddress: recipientAddress, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, totalAmount: computedTotal, buttonText: buttonText, themeColor: themeColor, returnUrl: returnUrl, returnLabel: returnLabel, onSuccess: onSuccess, onError: onError, classes: classes, defaultPaymentMethod: defaultPaymentMethod, senderAddress: senderAddress, showPoints: showPoints, showOrderId: showOrderId, callbackMetadata: checkoutFormMetadata, isFormValid: isFormValid, feeOnTop: feeOnTop })] }), cartPanel: _jsx(CheckoutCartPanel, { items: items, totalAmount: computedTotal, tokenSymbol: tokenSymbol, tokenDecimals: tokenDecimals, organizationName: organizationName, organizationLogo: organizationLogo, classes: classes, footer: footer, shipping: effectiveShipping, tax: typeof tax === "string" ? { amount: tax } : tax, discount: effectiveDiscount, summaryLines: summaryLines, usdEquivalent: usdEquivalent }), classes: classes }) }) }));
|
|
201
|
+
return (_jsx(AnySpendFingerprintWrapper, { fingerprint: fingerprint, children: _jsx(AnySpendCustomizationProvider, { slots: slots, content: content, theme: theme, children: _jsx(CheckoutLayout, { mode: mode, paymentPanel: _jsxs(_Fragment, { children: [isVariablePricingActive && tokenData && variablePricing && (_jsx(VariablePricingInput, { config: variablePricing, tokenDecimals: tokenDecimals, tokenSymbol: tokenSymbol, themeColor: themeColor, onChange: setVariablePricingAmount })), hasFormContent && (_jsxs("div", { className: "mb-6", children: [_jsx(CheckoutFormPanel, { formSchema: formSchema, formComponent: formComponent, shippingOptions: shippingOptions, collectShippingAddress: collectShippingAddress, enableDiscountCode: enableDiscountCode, validateDiscount: validateDiscount, tokenSymbol: tokenSymbol, tokenDecimals: tokenDecimals, classes: classes, formData: formData, onFormDataChange: handleFormDataChange, selectedShipping: selectedShipping, onShippingChange: handleShippingChange, appliedDiscount: appliedDiscount, onDiscountApplied: handleDiscountApplied, onDiscountRemoved: handleDiscountRemoved, shippingAddress: shippingAddress, onShippingAddressChange: setShippingAddress, checkoutFormSlot: slots?.checkoutForm }), _jsx("div", { className: "mt-6 border-t border-gray-200 dark:border-neutral-700" })] })), _jsx(CheckoutPaymentPanel, { recipientAddress: recipientAddress, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, totalAmount: computedTotal, buttonText: buttonText, themeColor: themeColor, returnUrl: returnUrl, returnLabel: returnLabel, onSuccess: onSuccess, onError: onError, classes: classes, defaultPaymentMethod: defaultPaymentMethod, senderAddress: senderAddress, showPoints: showPoints, showOrderId: showOrderId, callbackMetadata: checkoutFormMetadata, isFormValid: isFormValid, feeOnTop: feeOnTop })] }), cartPanel: _jsx(CheckoutCartPanel, { items: items, totalAmount: computedTotal, tokenSymbol: tokenSymbol, tokenDecimals: tokenDecimals, organizationName: organizationName, organizationLogo: organizationLogo, classes: classes, footer: footer, shipping: effectiveShipping, tax: typeof tax === "string" ? { amount: tax } : tax, discount: effectiveDiscount, summaryLines: summaryLines, usdEquivalent: usdEquivalent }), classes: classes }) }) }));
|
|
155
202
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface VariablePricingConfig {
|
|
2
|
+
enabled: boolean;
|
|
3
|
+
minAmount?: string;
|
|
4
|
+
maxAmount?: string;
|
|
5
|
+
suggestedAmount?: string;
|
|
6
|
+
label?: string;
|
|
7
|
+
currency?: string;
|
|
8
|
+
}
|
|
9
|
+
interface VariablePricingInputProps {
|
|
10
|
+
config: VariablePricingConfig;
|
|
11
|
+
tokenDecimals: number;
|
|
12
|
+
tokenSymbol: string;
|
|
13
|
+
themeColor?: string;
|
|
14
|
+
onChange: (amountWei: string) => void;
|
|
15
|
+
}
|
|
16
|
+
export declare function VariablePricingInput({ config, tokenDecimals, tokenSymbol, themeColor, onChange, }: VariablePricingInputProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export {};
|