@blocklet/payment-react 1.20.5 → 1.20.7
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/.aigne/doc-smith/config.yaml +2 -2
- package/.aigne/doc-smith/upload-cache.yaml +381 -0
- package/docs/components-business-auto-topup.md +128 -179
- package/docs/components-business-overdue-invoice-payment.md +108 -143
- package/docs/components-business-resume-subscription.md +117 -104
- package/docs/components-business.md +12 -36
- package/docs/components-checkout-checkout-donate.md +209 -149
- package/docs/components-checkout-checkout-form.md +115 -136
- package/docs/components-checkout-checkout-table.md +92 -172
- package/docs/components-checkout.md +43 -109
- package/docs/components-history-credit-grants-list.md +45 -70
- package/docs/components-history-credit-transactions-list.md +57 -67
- package/docs/components-history-invoice-list.md +58 -52
- package/docs/components-history-payment-list.md +19 -40
- package/docs/components-history.md +42 -67
- package/docs/components-ui-form-elements-address-form.md +37 -65
- package/docs/components-ui-form-elements-country-select.md +80 -59
- package/docs/components-ui-form-elements-currency-selector.md +57 -73
- package/docs/components-ui-form-elements-phone-input.md +90 -112
- package/docs/components-ui-form-elements.md +46 -80
- package/docs/components-ui-payment-summary.md +71 -119
- package/docs/components-ui-pricing-table.md +117 -204
- package/docs/components-ui.md +59 -32
- package/docs/components.md +89 -62
- package/docs/getting-started.md +36 -63
- package/docs/guides-theming.md +122 -84
- package/docs/guides-utilities.md +107 -145
- package/docs/guides.md +7 -84
- package/docs/hooks-use-mobile.md +50 -36
- package/docs/hooks-use-subscription.md +72 -89
- package/docs/hooks.md +12 -82
- package/docs/overview.md +45 -52
- package/docs/providers-donate-provider.md +73 -95
- package/docs/providers-payment-provider.md +115 -169
- package/docs/providers.md +27 -86
- package/es/locales/en.js +7 -0
- package/es/locales/zh.js +8 -1
- package/es/payment/index.js +3 -0
- package/es/payment/progress-item.d.ts +12 -0
- package/es/payment/progress-item.js +78 -0
- package/es/payment/success.d.ts +4 -1
- package/es/payment/success.js +55 -3
- package/lib/locales/en.js +7 -0
- package/lib/locales/zh.js +8 -1
- package/lib/payment/index.js +3 -0
- package/lib/payment/progress-item.d.ts +12 -0
- package/lib/payment/progress-item.js +107 -0
- package/lib/payment/success.d.ts +4 -1
- package/lib/payment/success.js +59 -3
- package/package.json +3 -3
- package/src/locales/en.tsx +7 -0
- package/src/locales/zh.tsx +8 -1
- package/src/payment/index.tsx +6 -0
- package/src/payment/progress-item.tsx +107 -0
- package/src/payment/success.tsx +88 -3
|
@@ -1,227 +1,140 @@
|
|
|
1
1
|
# PricingTable
|
|
2
2
|
|
|
3
|
-
The `PricingTable` component is a flexible UI element designed to display subscription plans and pricing options in a structured,
|
|
3
|
+
The `PricingTable` component is a flexible UI element designed to display subscription plans and pricing options in a structured, responsive table. It allows users to toggle between billing cycles (e.g., monthly, yearly), select their preferred currency, and choose a plan to proceed with.
|
|
4
4
|
|
|
5
|
-
This component
|
|
6
|
-
|
|
7
|
-
For a more integrated solution that bundles the pricing table with the complete checkout flow, consider using the higher-level [`CheckoutTable`](./components-checkout-checkout-table.md) component.
|
|
8
|
-
|
|
9
|
-
```d2
|
|
10
|
-
direction: down
|
|
11
|
-
|
|
12
|
-
"PaymentProvider": {
|
|
13
|
-
shape: class
|
|
14
|
-
"Provides Context (Settings, Currency, etc.)"
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
"Your Application": {
|
|
18
|
-
shape: class
|
|
19
|
-
"Provides `table` data"
|
|
20
|
-
"Implements `onSelect` handler"
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
"PricingTable": {
|
|
24
|
-
shape: package
|
|
25
|
-
"Renders UI"
|
|
26
|
-
" - Billing Cycle Toggles"
|
|
27
|
-
" - Currency Selector"
|
|
28
|
-
" - Plan Cards"
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
"User": {
|
|
32
|
-
shape: person
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
"PaymentProvider" -> "PricingTable": "Provides context"
|
|
36
|
-
"Your Application" -> "PricingTable": "Passes props (`table`, `onSelect`)"
|
|
37
|
-
"User" -> "PricingTable": "Interacts (selects plan)"
|
|
38
|
-
"PricingTable" -> "Your Application": "Triggers `onSelect(priceId, currencyId)`"
|
|
39
|
-
|
|
40
|
-
```
|
|
5
|
+
This component is ideal for building custom checkout flows where you need granular control over the presentation of pricing plans. For a more integrated solution that handles the entire checkout process, consider using the higher-level [`CheckoutTable`](./components-checkout-checkout-table.md) component.
|
|
41
6
|
|
|
42
7
|
## Props
|
|
43
8
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
|
47
|
-
|
|
48
|
-
| `
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
9
|
+
| Prop | Type | Default | Description |
|
|
10
|
+
| --- | --- | --- | --- |
|
|
11
|
+
| `table` | `TPricingTableExpanded` | - | **Required**. An object containing the pricing table data, including a list of items (plans), currency information, and other details. |
|
|
12
|
+
| `onSelect` | `(priceId: string, currencyId: string) => void` | - | **Required**. A callback function that is triggered when a user clicks the action button for a plan. It receives the selected `priceId` and `currencyId`. |
|
|
13
|
+
| `alignItems` | `'center' \| 'left'` | `'center'` | Controls the horizontal alignment of the table's header content (billing cycle and currency selectors). |
|
|
14
|
+
| `mode` | `'checkout' \| 'select'` | `'checkout'` | Determines the behavior and text of the action button. `'checkout'` mode is for initiating a payment, while `'select'` mode is for selecting a plan within a larger form. |
|
|
15
|
+
| `interval` | `string` | `''` | Sets the initially selected billing interval. The format is typically `interval-interval_count` (e.g., `month-1`, `year-1`). |
|
|
16
|
+
| `hideCurrency` | `boolean` | `false` | If `true`, the currency selector dropdown will be hidden, even if multiple currencies are available. |
|
|
17
|
+
|
|
18
|
+
## Usage Example
|
|
19
|
+
|
|
20
|
+
To use the `PricingTable`, you must wrap it in a `PaymentProvider`. The component requires a `table` object with your product data and an `onSelect` handler to manage user selections.
|
|
21
|
+
|
|
22
|
+
```tsx Integration Example icon=lucide:code
|
|
23
|
+
import { PaymentProvider } from '@blocklet/payment-react';
|
|
24
|
+
import { PricingTable } from '@blocklet/payment-react/components/ui';
|
|
25
|
+
import type { TPricingTableExpanded } from '@blocklet/payment-types';
|
|
26
|
+
|
|
27
|
+
// In a real application, you would fetch this data from your payment service.
|
|
28
|
+
const pricingTableData: TPricingTableExpanded = {
|
|
29
|
+
id: 'pt_123',
|
|
30
|
+
livemode: false,
|
|
31
|
+
currency: { id: 'usd', symbol: '$' },
|
|
32
|
+
items: [
|
|
33
|
+
{
|
|
34
|
+
price_id: 'price_basic_monthly',
|
|
35
|
+
product: {
|
|
36
|
+
name: 'Basic Plan',
|
|
37
|
+
description: 'For individuals and small teams.',
|
|
38
|
+
unit_label: 'user',
|
|
39
|
+
features: [{ name: '5 Projects' }, { name: '10GB Storage' }, { name: 'Basic Support' }],
|
|
40
|
+
},
|
|
41
|
+
price: {
|
|
42
|
+
currency: 'usd',
|
|
43
|
+
unit_amount: '1000', // in cents
|
|
44
|
+
recurring: { interval: 'month', interval_count: 1 },
|
|
45
|
+
currency_options: [{ currency_id: 'usd', unit_amount: '1000' }],
|
|
46
|
+
},
|
|
47
|
+
is_highlight: false,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
price_id: 'price_pro_monthly',
|
|
51
|
+
product: {
|
|
52
|
+
name: 'Pro Plan',
|
|
53
|
+
description: 'For growing businesses.',
|
|
54
|
+
unit_label: 'user',
|
|
55
|
+
features: [{ name: 'Unlimited Projects' }, { name: '100GB Storage' }, { name: 'Priority Support' }],
|
|
56
|
+
},
|
|
57
|
+
price: {
|
|
58
|
+
currency: 'usd',
|
|
59
|
+
unit_amount: '2500',
|
|
60
|
+
recurring: { interval: 'month', interval_count: 1 },
|
|
61
|
+
currency_options: [{ currency_id: 'usd', unit_amount: '2500' }],
|
|
62
|
+
},
|
|
63
|
+
is_highlight: true,
|
|
64
|
+
highlight_text: 'Popular',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
price_id: 'price_basic_yearly',
|
|
68
|
+
product: {
|
|
69
|
+
name: 'Basic Plan',
|
|
70
|
+
description: 'For individuals and small teams.',
|
|
71
|
+
unit_label: 'user',
|
|
72
|
+
features: [{ name: '5 Projects' }, { name: '10GB Storage' }, { name: 'Basic Support' }],
|
|
73
|
+
},
|
|
74
|
+
price: {
|
|
75
|
+
currency: 'usd',
|
|
76
|
+
unit_amount: '10000',
|
|
77
|
+
recurring: { interval: 'year', interval_count: 1 },
|
|
78
|
+
currency_options: [{ currency_id: 'usd', unit_amount: '10000' }],
|
|
79
|
+
},
|
|
80
|
+
is_highlight: false,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
price_id: 'price_pro_yearly',
|
|
84
|
+
product: {
|
|
85
|
+
name: 'Pro Plan',
|
|
86
|
+
description: 'For growing businesses.',
|
|
87
|
+
unit_label: 'user',
|
|
88
|
+
features: [{ name: 'Unlimited Projects' }, { name: '100GB Storage' }, { name: 'Priority Support' }],
|
|
89
|
+
},
|
|
90
|
+
price: {
|
|
91
|
+
currency: 'usd',
|
|
92
|
+
unit_amount: '25000',
|
|
93
|
+
recurring: { interval: 'year', interval_count: 1 },
|
|
94
|
+
currency_options: [{ currency_id: 'usd', unit_amount: '25000' }],
|
|
95
|
+
},
|
|
96
|
+
is_highlight: true,
|
|
97
|
+
highlight_text: 'Popular',
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
};
|
|
66
101
|
|
|
67
|
-
|
|
102
|
+
function MyPricingPage() {
|
|
103
|
+
const { session, connect } = useSessionContext();
|
|
68
104
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
//
|
|
105
|
+
const handlePlanSelect = async (priceId: string, currencyId: string) => {
|
|
106
|
+
console.log(`Plan selected: ${priceId}, Currency: ${currencyId}`);
|
|
107
|
+
// Here, you would typically navigate to a checkout page or open a payment modal.
|
|
108
|
+
// For example: `router.push(\"/checkout?price_id=${priceId}¤cy_id=${currencyId}\")`
|
|
109
|
+
alert(`Selected Price ID: ${priceId}`);
|
|
73
110
|
};
|
|
74
111
|
|
|
75
112
|
return (
|
|
76
|
-
<
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Your component must be wrapped in PaymentProvider
|
|
84
|
-
function AppWithPayment() {
|
|
85
|
-
const { session, connectApi } = useSessionContext();
|
|
86
|
-
|
|
87
|
-
if (!session.user) {
|
|
88
|
-
return <button onClick={connectApi}>Connect Wallet</button>;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Assume 'myPricingTableData' is available here
|
|
92
|
-
return (
|
|
93
|
-
<PaymentProvider session={session} connect={connectApi}>
|
|
94
|
-
<MyPricingPage myPricingTableData={myPricingTableData} />
|
|
113
|
+
<PaymentProvider session={session} connect={connect}>
|
|
114
|
+
<div style={{ maxWidth: 800, margin: 'auto' }}>
|
|
115
|
+
<PricingTable table={pricingTableData} onSelect={handlePlanSelect} />
|
|
116
|
+
</div>
|
|
95
117
|
</PaymentProvider>
|
|
96
118
|
);
|
|
97
119
|
}
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
**Note:** The `useSessionContext` hook should be set up in your application to provide session information. For a detailed guide on how to configure this and the `PaymentProvider`, please see the [PaymentProvider documentation](./providers-payment-provider.md).
|
|
101
|
-
|
|
102
|
-
### Plan Selection Mode
|
|
103
120
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
In this mode, you need to manage the selected plan in your parent component's state and pass the `is_selected` property down to the `table` items.
|
|
107
|
-
|
|
108
|
-
```jsx
|
|
109
|
-
import React, { useState, useMemo } from 'react';
|
|
110
|
-
import PricingTable from '@blocklet/payment-react/lib/components/pricing-table';
|
|
111
|
-
import { PaymentProvider } from '@blocklet/payment-react/lib/contexts/payment';
|
|
112
|
-
import { useSessionContext } from '../hooks/session'; // Your local session context hook
|
|
113
|
-
|
|
114
|
-
function PlanSelectionForm({ myPricingTableData }) {
|
|
115
|
-
const [selectedPriceId, setSelectedPriceId] = useState(null);
|
|
116
|
-
|
|
117
|
-
const handlePlanSelect = (priceId, currencyId) => {
|
|
118
|
-
setSelectedPriceId(priceId);
|
|
119
|
-
console.log(`User selected price: ${priceId} in currency: ${currencyId}`);
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
// Add is_selected property to the items based on the current state
|
|
123
|
-
const tableDataWithSelection = useMemo(() => ({
|
|
124
|
-
...myPricingTableData,
|
|
125
|
-
items: myPricingTableData.items.map(item => ({
|
|
126
|
-
...item,
|
|
127
|
-
is_selected: item.price_id === selectedPriceId,
|
|
128
|
-
})),
|
|
129
|
-
}), [myPricingTableData, selectedPriceId]);
|
|
130
|
-
|
|
131
|
-
return (
|
|
132
|
-
<div>
|
|
133
|
-
<h2>Choose Your Plan</h2>
|
|
134
|
-
<PricingTable
|
|
135
|
-
table={tableDataWithSelection}
|
|
136
|
-
onSelect={handlePlanSelect}
|
|
137
|
-
mode="select"
|
|
138
|
-
alignItems="left"
|
|
139
|
-
/>
|
|
140
|
-
<button disabled={!selectedPriceId}>Continue to Checkout</button>
|
|
141
|
-
</div>
|
|
142
|
-
);
|
|
143
|
-
}
|
|
121
|
+
export default MyPricingPage;
|
|
122
|
+
```
|
|
144
123
|
|
|
145
|
-
|
|
146
|
-
function AppWithPaymentSelection() {
|
|
147
|
-
const { session, connectApi } = useSessionContext();
|
|
124
|
+
## Usage Scenarios
|
|
148
125
|
|
|
149
|
-
|
|
150
|
-
return <button onClick={connectApi}>Connect Wallet</button>;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Assume 'myPricingTableData' is available here
|
|
154
|
-
return (
|
|
155
|
-
<PaymentProvider session={session} connect={connectApi}>
|
|
156
|
-
<PlanSelectionForm myPricingTableData={myPricingTableData} />
|
|
157
|
-
</PaymentProvider>
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
```
|
|
126
|
+
### Mode: `checkout` vs. `select`
|
|
161
127
|
|
|
162
|
-
|
|
128
|
+
The `mode` prop changes the call-to-action button to fit different use cases.
|
|
163
129
|
|
|
164
|
-
The
|
|
130
|
+
- **`mode='checkout'` (Default):** The button text will be context-aware, showing labels like "Subscribe" or "Start Trial". This mode is intended for when the user's click should immediately initiate the payment or checkout process.
|
|
165
131
|
|
|
166
|
-
-
|
|
167
|
-
- **`livemode`**: A boolean indicating if the table is in live or test mode.
|
|
168
|
-
- **`currency`**: A default currency object.
|
|
169
|
-
- **`items`**: An array of `TPricingTableItem` objects. Each item represents a single plan and contains:
|
|
170
|
-
- **`price_id`**: The unique ID for the price.
|
|
171
|
-
- **`product`**: An object with product details like `name`, `description`, and an array of `features`.
|
|
172
|
-
- **`price`**: An object with pricing details, including `unit_amount`, `currency_options`, and a `recurring` object that specifies the billing `interval` (e.g., 'month', 'year') and `interval_count`.
|
|
173
|
-
- **`is_highlight`** (optional): A boolean to highlight a specific plan.
|
|
174
|
-
- **`highlight_text`** (optional): Text to display in the highlight chip (e.g., "Most Popular").
|
|
132
|
+
- **`mode='select'`:** The button text will show "Select" or "Selected". This is useful when the pricing table is part of a larger form or multi-step process. The `onSelect` callback can be used to update the application's state with the chosen plan, and the UI will visually indicate which plan is currently selected.
|
|
175
133
|
|
|
176
|
-
###
|
|
134
|
+
### Handling `onSelect`
|
|
177
135
|
|
|
178
|
-
|
|
179
|
-
{
|
|
180
|
-
"id": "pt_12345",
|
|
181
|
-
"livemode": true,
|
|
182
|
-
"currency": { "id": "usd", "symbol": "$" },
|
|
183
|
-
"items": [
|
|
184
|
-
{
|
|
185
|
-
"price_id": "price_basic_monthly",
|
|
186
|
-
"product": {
|
|
187
|
-
"name": "Basic Plan",
|
|
188
|
-
"description": "For individuals and small teams.",
|
|
189
|
-
"features": [
|
|
190
|
-
{ "name": "5 Projects" },
|
|
191
|
-
{ "name": "Basic Analytics" },
|
|
192
|
-
{ "name": "24/7 Support" }
|
|
193
|
-
],
|
|
194
|
-
"unit_label": "user"
|
|
195
|
-
},
|
|
196
|
-
"price": {
|
|
197
|
-
"unit_amount": "1000",
|
|
198
|
-
"currency_options": [{ "currency_id": "usd", "unit_amount": "1000" }],
|
|
199
|
-
"recurring": { "interval": "month", "interval_count": 1 }
|
|
200
|
-
},
|
|
201
|
-
"is_highlight": false
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
"price_id": "price_pro_yearly",
|
|
205
|
-
"product": {
|
|
206
|
-
"name": "Pro Plan",
|
|
207
|
-
"description": "For growing businesses.",
|
|
208
|
-
"features": [
|
|
209
|
-
{ "name": "Unlimited Projects" },
|
|
210
|
-
{ "name": "Advanced Analytics" },
|
|
211
|
-
{ "name": "Priority Support" }
|
|
212
|
-
],
|
|
213
|
-
"unit_label": "user"
|
|
214
|
-
},
|
|
215
|
-
"price": {
|
|
216
|
-
"unit_amount": "25000",
|
|
217
|
-
"currency_options": [{ "currency_id": "usd", "unit_amount": "25000" }],
|
|
218
|
-
"recurring": { "interval": "year", "interval_count": 1 }
|
|
219
|
-
},
|
|
220
|
-
"is_highlight": true,
|
|
221
|
-
"highlight_text": "Popular"
|
|
222
|
-
}
|
|
223
|
-
]
|
|
224
|
-
}
|
|
225
|
-
```
|
|
136
|
+
The `onSelect` callback is the core mechanism for handling user interaction. It's an async function that receives the `priceId` and `currencyId` of the chosen plan. Your application logic should reside here. Common actions include:
|
|
226
137
|
|
|
227
|
-
|
|
138
|
+
- Storing the selected plan in your application's state.
|
|
139
|
+
- Redirecting the user to a dedicated checkout page, passing the `priceId` as a URL parameter.
|
|
140
|
+
- Using the `priceId` to create a checkout session with the payment service backend and then opening a payment form.
|
package/docs/components-ui.md
CHANGED
|
@@ -1,44 +1,71 @@
|
|
|
1
1
|
# UI Components
|
|
2
2
|
|
|
3
|
-
The
|
|
4
|
-
|
|
5
|
-
This approach allows you to integrate payment functionality seamlessly into your existing application design. You can combine these components to construct a checkout process that is tailored to your specific requirements, as illustrated in the workflow below.
|
|
6
|
-
|
|
7
|
-
```d2
|
|
8
|
-
direction: down
|
|
9
|
-
|
|
10
|
-
A: "Display PricingTable Component"
|
|
11
|
-
B: "User Selects a Subscription Plan"
|
|
12
|
-
C: "Application State is Updated via onSelect Callback"
|
|
13
|
-
D: "Render PaymentSummary with Order Details"
|
|
14
|
-
E: "Render Form Elements (e.g., AddressForm)"
|
|
15
|
-
F: "User Clicks Custom 'Pay' Button"
|
|
16
|
-
G: "Application Logic Submits Payment to Backend"
|
|
17
|
-
|
|
18
|
-
A -> B: "User Action"
|
|
19
|
-
B -> C: "Triggers Callback"
|
|
20
|
-
C -> D: "Re-renders UI"
|
|
21
|
-
D -> E
|
|
22
|
-
E -> F: "User provides info"
|
|
23
|
-
F -> G: "Initiates Submission"
|
|
24
|
-
```
|
|
3
|
+
The `@blocklet/payment-react` library provides a set of granular UI Components designed to give you maximum flexibility when building your payment and checkout interfaces. Unlike the high-level [Checkout Components](./components-checkout.md), which encapsulate entire flows, these components are the building blocks for creating a custom user experience.
|
|
25
4
|
|
|
26
|
-
|
|
5
|
+
These components are ideal when you need to integrate payment functionality into an existing application layout or when the standard checkout flows do not meet your specific design requirements.
|
|
27
6
|
|
|
28
7
|
<x-cards data-columns="3">
|
|
29
|
-
<x-card data-title="PricingTable" data-href="/components/ui/pricing-table"
|
|
30
|
-
|
|
8
|
+
<x-card data-title="PricingTable" data-icon="lucide:layout-list" data-href="/components/ui/pricing-table">
|
|
9
|
+
Display subscription plans and pricing options in a structured table, allowing users to select a plan and proceed to checkout.
|
|
31
10
|
</x-card>
|
|
32
|
-
<x-card data-title="PaymentSummary" data-href="/components/ui/payment-summary"
|
|
33
|
-
|
|
11
|
+
<x-card data-title="PaymentSummary" data-icon="lucide:receipt" data-href="/components/ui/payment-summary">
|
|
12
|
+
Show a detailed summary of an order, including line items, totals, and trial information within the checkout flow.
|
|
34
13
|
</x-card>
|
|
35
|
-
<x-card data-title="Form Elements" data-href="/components/ui/form-elements"
|
|
36
|
-
A
|
|
14
|
+
<x-card data-title="Form Elements" data-icon="lucide:form-input" data-href="/components/ui/form-elements">
|
|
15
|
+
A collection of specialized input components for building custom payment and contact information forms, such as address, phone, and country selection.
|
|
37
16
|
</x-card>
|
|
38
17
|
</x-cards>
|
|
39
18
|
|
|
40
|
-
|
|
19
|
+
## Composing Your Payment UI
|
|
20
|
+
|
|
21
|
+
UI Components are meant to be composed together to construct a complete payment page. Most of these components require access to the payment context for data like payment methods and settings, so they must be rendered within a `PaymentProvider`.
|
|
22
|
+
|
|
23
|
+
Below is a conceptual example of how you might combine `PricingTable` and `PaymentSummary` to create a custom checkout page.
|
|
24
|
+
|
|
25
|
+
```jsx A Custom Checkout Page icon=logos:react
|
|
26
|
+
import { PaymentProvider } from '@blocklet/payment-react';
|
|
27
|
+
import { PricingTable, PaymentSummary } from '@blocklet/payment-react/components';
|
|
28
|
+
// The useSessionContext hook is defined in the PaymentProvider documentation
|
|
29
|
+
import { useSessionContext } from '/path/to/session/context';
|
|
30
|
+
|
|
31
|
+
function CustomCheckoutPage() {
|
|
32
|
+
const { session, connectApi } = useSessionContext();
|
|
33
|
+
|
|
34
|
+
// In a real application, you would fetch this data from your backend
|
|
35
|
+
const pricingData = { /* ... pricing table data object ... */ };
|
|
36
|
+
const selectedItems = [ /* ... line items based on user selection ... */ ];
|
|
37
|
+
const currency = { /* ... currency object ... */ };
|
|
38
|
+
|
|
39
|
+
const handleSelect = (priceId, currencyId) => {
|
|
40
|
+
console.log('User selected plan:', priceId, 'with currency:', currencyId);
|
|
41
|
+
// Add the selected plan to the 'selectedItems' state and update the UI
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<PaymentProvider
|
|
46
|
+
apiHost={connectApi}
|
|
47
|
+
sessionId={session.user?.did}
|
|
48
|
+
locale="en"
|
|
49
|
+
>
|
|
50
|
+
<div className="checkout-container" style={{ display: 'flex', gap: '2rem' }}>
|
|
51
|
+
<div className="pricing-section" style={{ flex: 2 }}>
|
|
52
|
+
<h2>Choose Your Plan</h2>
|
|
53
|
+
<PricingTable table={pricingData} onSelect={handleSelect} />
|
|
54
|
+
</div>
|
|
55
|
+
<div className="summary-section" style={{ flex: 1 }}>
|
|
56
|
+
<h2>Order Summary</h2>
|
|
57
|
+
<PaymentSummary items={selectedItems} currency={currency} />
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</PaymentProvider>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
In this example, `PricingTable` and `PaymentSummary` are used together on a custom page. The `PaymentProvider` wraps the entire structure, making payment settings and methods available to all child components.
|
|
66
|
+
|
|
67
|
+
## Next Steps
|
|
41
68
|
|
|
42
|
-
|
|
69
|
+
Now that you understand the role of UI Components, dive into the specifics of each one to start building your custom payment flow. We recommend starting with the `PricingTable`.
|
|
43
70
|
|
|
44
|
-
|
|
71
|
+
[Learn about the PricingTable component →](./components-ui-pricing-table.md)
|