@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.
Files changed (55) hide show
  1. package/.aigne/doc-smith/config.yaml +2 -2
  2. package/.aigne/doc-smith/upload-cache.yaml +381 -0
  3. package/docs/components-business-auto-topup.md +128 -179
  4. package/docs/components-business-overdue-invoice-payment.md +108 -143
  5. package/docs/components-business-resume-subscription.md +117 -104
  6. package/docs/components-business.md +12 -36
  7. package/docs/components-checkout-checkout-donate.md +209 -149
  8. package/docs/components-checkout-checkout-form.md +115 -136
  9. package/docs/components-checkout-checkout-table.md +92 -172
  10. package/docs/components-checkout.md +43 -109
  11. package/docs/components-history-credit-grants-list.md +45 -70
  12. package/docs/components-history-credit-transactions-list.md +57 -67
  13. package/docs/components-history-invoice-list.md +58 -52
  14. package/docs/components-history-payment-list.md +19 -40
  15. package/docs/components-history.md +42 -67
  16. package/docs/components-ui-form-elements-address-form.md +37 -65
  17. package/docs/components-ui-form-elements-country-select.md +80 -59
  18. package/docs/components-ui-form-elements-currency-selector.md +57 -73
  19. package/docs/components-ui-form-elements-phone-input.md +90 -112
  20. package/docs/components-ui-form-elements.md +46 -80
  21. package/docs/components-ui-payment-summary.md +71 -119
  22. package/docs/components-ui-pricing-table.md +117 -204
  23. package/docs/components-ui.md +59 -32
  24. package/docs/components.md +89 -62
  25. package/docs/getting-started.md +36 -63
  26. package/docs/guides-theming.md +122 -84
  27. package/docs/guides-utilities.md +107 -145
  28. package/docs/guides.md +7 -84
  29. package/docs/hooks-use-mobile.md +50 -36
  30. package/docs/hooks-use-subscription.md +72 -89
  31. package/docs/hooks.md +12 -82
  32. package/docs/overview.md +45 -52
  33. package/docs/providers-donate-provider.md +73 -95
  34. package/docs/providers-payment-provider.md +115 -169
  35. package/docs/providers.md +27 -86
  36. package/es/locales/en.js +7 -0
  37. package/es/locales/zh.js +8 -1
  38. package/es/payment/index.js +3 -0
  39. package/es/payment/progress-item.d.ts +12 -0
  40. package/es/payment/progress-item.js +78 -0
  41. package/es/payment/success.d.ts +4 -1
  42. package/es/payment/success.js +55 -3
  43. package/lib/locales/en.js +7 -0
  44. package/lib/locales/zh.js +8 -1
  45. package/lib/payment/index.js +3 -0
  46. package/lib/payment/progress-item.d.ts +12 -0
  47. package/lib/payment/progress-item.js +107 -0
  48. package/lib/payment/success.d.ts +4 -1
  49. package/lib/payment/success.js +59 -3
  50. package/package.json +3 -3
  51. package/src/locales/en.tsx +7 -0
  52. package/src/locales/zh.tsx +8 -1
  53. package/src/payment/index.tsx +6 -0
  54. package/src/payment/progress-item.tsx +107 -0
  55. 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, user-friendly table. It allows users to browse different plans, switch between billing cycles (e.g., monthly, yearly), select a currency, and proceed to checkout by selecting a plan.
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 must be used within the context of a `PaymentProvider`, as it relies on the provider for payment settings and currency information. For detailed instructions on setting up the provider, refer to the [PaymentProvider documentation](./providers-payment-provider.md).
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
- The `PricingTable` component accepts the following props to customize its behavior and appearance:
45
-
46
- | Prop | Type | Required | Default | Description |
47
- |---|---|---|---|---|
48
- | `table` | `TPricingTableExpanded` | Yes | - | An object containing the pricing table data, including a list of items (plans) to display. |
49
- | `onSelect` | `(priceId: string, currencyId: string) => void` | Yes | - | A callback function that is invoked when a user clicks the action button for a plan. |
50
- | `alignItems` | `'center' \| 'left'` | No | `'center'` | Controls the horizontal alignment of the pricing plans and controls. |
51
- | `mode` | `'checkout' \| 'select'` | No | `'checkout'` | Determines the behavior and text of the action button. `'checkout'` is for direct payment, while `'select'` is for plan selection. |
52
- | `interval` | `string` | No | `''` | The initially selected billing interval (e.g., 'month-1', 'year-1'). If empty, the first available interval is used. |
53
- | `hideCurrency` | `boolean` | No | `false` | If `true`, the currency selection dropdown will be hidden from the user. |
54
-
55
- ## Usage Scenarios
56
-
57
- ### Basic Checkout Table
58
-
59
- This is the default mode. The component displays plans with a subscription button. When a user clicks the button, the `onSelect` callback is triggered, which you can use to initiate a checkout session.
60
-
61
- ```jsx
62
- import React from 'react';
63
- import PricingTable from '@blocklet/payment-react/lib/components/pricing-table';
64
- import { PaymentProvider } from '@blocklet/payment-react/lib/contexts/payment';
65
- import { useSessionContext } from '../hooks/session'; // Your local session context hook
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
- // Assume 'myPricingTableData' is fetched from your backend and conforms to TPricingTableExpanded
102
+ function MyPricingPage() {
103
+ const { session, connect } = useSessionContext();
68
104
 
69
- function MyPricingPage({ myPricingTableData }) {
70
- const handleSubscription = async (priceId, currencyId) => {
71
- console.log(`Starting subscription for price: ${priceId} with currency: ${currencyId}`);
72
- // Add your logic to create a checkout session and redirect the user
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}&currency_id=${currencyId}\")`
109
+ alert(`Selected Price ID: ${priceId}`);
73
110
  };
74
111
 
75
112
  return (
76
- <PricingTable
77
- table={myPricingTableData}
78
- onSelect={handleSubscription}
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
- By setting `mode='select'`, the component can be used as part of a larger form where the user selects a plan before proceeding. The action button text changes to "Select" or "Selected", and selected items are highlighted with a border.
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
- // Your component must be wrapped in PaymentProvider
146
- function AppWithPaymentSelection() {
147
- const { session, connectApi } = useSessionContext();
124
+ ## Usage Scenarios
148
125
 
149
- if (!session.user) {
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
- ## Data Structure for `table` prop
128
+ The `mode` prop changes the call-to-action button to fit different use cases.
163
129
 
164
- The `table` prop expects an object with a specific structure, `TPricingTableExpanded`. Here's a simplified overview of what it contains:
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
- - **`id`**: A unique identifier for the pricing table.
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
- ### Example `table` Object
134
+ ### Handling `onSelect`
177
135
 
178
- ```json
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
- This component streamlines the creation of dynamic and interactive pricing pages. Once the user selects a plan, you can use the `onSelect` callback to guide them to the next step, which is often displaying a [PaymentSummary](./components-ui-payment-summary.md).
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.
@@ -1,44 +1,71 @@
1
1
  # UI Components
2
2
 
3
- The UI Components are a collection of granular, self-contained React components designed for building custom payment and checkout experiences. Unlike the high-level [Checkout Components](./components-checkout.md), which manage an entire payment flow, UI Components give you full control over the layout and user experience by providing the essential building blocks for your interface.
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
- Below is an overview of the core UI components available. Each component has its own detailed documentation page.
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" data-icon="lucide:table">
30
- Renders a structured, responsive table of your subscription plans. It handles logic for switching between billing intervals and currencies, allowing users to make a selection.
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" data-icon="lucide:receipt">
33
- Displays a detailed breakdown of an order, including line items, quantities, pricing, trial information, and the total amount due. Essential for transparency during checkout.
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" data-icon="lucide:pencil-ruler">
36
- A suite of individual inputs for collecting user data like billing addresses and phone numbers. They include built-in validation and are designed to be composed into any form.
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
- By combining these components, you can build a robust and user-friendly payment interface that fits perfectly within your application's design. To get started, explore the documentation for the component that best fits your immediate needs.
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
- Next, learn how to display your products and plans with the [PricingTable component](./components-ui-pricing-table.md).
71
+ [Learn about the PricingTable component &rarr;](./components-ui-pricing-table.md)