@blocklet/payment-react 1.19.23 → 1.20.1

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 (49) hide show
  1. package/.aigne/doc-smith/config.yaml +114 -0
  2. package/.aigne/doc-smith/output/structure-plan.json +361 -0
  3. package/.aigne/doc-smith/preferences.yml +55 -0
  4. package/.aigne/doc-smith/upload-cache.yaml +264 -0
  5. package/README.md +2 -3
  6. package/docs/_sidebar.md +33 -0
  7. package/docs/components-business-auto-topup.md +238 -0
  8. package/docs/components-business-overdue-invoice-payment.md +231 -0
  9. package/docs/components-business-resume-subscription.md +177 -0
  10. package/docs/components-business.md +45 -0
  11. package/docs/components-checkout-checkout-donate.md +199 -0
  12. package/docs/components-checkout-checkout-form.md +185 -0
  13. package/docs/components-checkout-checkout-table.md +228 -0
  14. package/docs/components-checkout.md +131 -0
  15. package/docs/components-history-credit-grants-list.md +98 -0
  16. package/docs/components-history-credit-transactions-list.md +116 -0
  17. package/docs/components-history-invoice-list.md +104 -0
  18. package/docs/components-history-payment-list.md +65 -0
  19. package/docs/components-history.md +92 -0
  20. package/docs/components-ui-form-elements-address-form.md +150 -0
  21. package/docs/components-ui-form-elements-country-select.md +105 -0
  22. package/docs/components-ui-form-elements-currency-selector.md +124 -0
  23. package/docs/components-ui-form-elements-phone-input.md +160 -0
  24. package/docs/components-ui-form-elements.md +125 -0
  25. package/docs/components-ui-payment-summary.md +157 -0
  26. package/docs/components-ui-pricing-table.md +227 -0
  27. package/docs/components-ui.md +44 -0
  28. package/docs/components.md +95 -0
  29. package/docs/getting-started.md +111 -0
  30. package/docs/guides-theming.md +175 -0
  31. package/docs/guides-utilities.md +235 -0
  32. package/docs/guides.md +95 -0
  33. package/docs/hooks-use-mobile.md +70 -0
  34. package/docs/hooks-use-subscription.md +129 -0
  35. package/docs/hooks.md +84 -0
  36. package/docs/overview.md +87 -0
  37. package/docs/providers-donate-provider.md +175 -0
  38. package/docs/providers-payment-provider.md +245 -0
  39. package/docs/providers.md +101 -0
  40. package/es/libs/util.d.ts +1 -1
  41. package/es/payment/form/index.js +15 -1
  42. package/es/payment/summary.js +1 -1
  43. package/lib/libs/util.d.ts +1 -1
  44. package/lib/payment/form/index.js +14 -1
  45. package/lib/payment/summary.js +1 -1
  46. package/package.json +9 -9
  47. package/src/libs/util.ts +1 -0
  48. package/src/payment/form/index.tsx +16 -1
  49. package/src/payment/summary.tsx +1 -2
@@ -0,0 +1,116 @@
1
+ # CreditTransactionsList
2
+
3
+ The `CreditTransactionsList` component renders a detailed and paginated table of credit transactions. It serves as a comprehensive log, allowing users to track how their credits have been utilized or adjusted over time. This component is essential for providing transparency in credit-based billing systems.
4
+
5
+ ### Context Requirement
6
+
7
+ This component requires access to the session context to identify the current user. Therefore, it must be rendered within a `PaymentProvider`. For details on setting up the provider and a `useSessionContext` hook, please refer to the [PaymentProvider documentation](./providers-payment-provider.md).
8
+
9
+ ### Properties
10
+
11
+ The `CreditTransactionsList` component accepts the following properties:
12
+
13
+ | Prop | Type | Description | Default |
14
+ | --- | --- | --- | --- |
15
+ | `customer_id` | `string` | The ID of the customer whose transactions are to be displayed. If omitted, it defaults to the DID of the currently logged-in user from the session context. | `session.user.did` |
16
+ | `subscription_id` | `string` | Filters the transactions to show only those related to a specific subscription ID. | `''` |
17
+ | `credit_grant_id` | `string` | Filters the transactions to show only those related to a specific credit grant ID. | `''` |
18
+ | `pageSize` | `number` | The number of transactions to display per page. | `10` |
19
+ | `onTableDataChange` | `(data, prevData) => void` | A callback function that is triggered when the transaction data is fetched or updated. It receives the new data and the previous data as arguments. | `() => {}` |
20
+ | `showAdminColumns` | `boolean` | If `true`, additional columns relevant to administrators (such as 'Meter Event') are displayed. This only applies if the logged-in user has an 'owner' or 'admin' role. | `false` |
21
+ | `showTimeFilter` | `boolean` | If `true`, a date range picker is displayed above the table, allowing users to filter transactions by a specific time period. | `false` |
22
+ | `source` | `string` | An optional string to filter transactions by their source. | `''` |
23
+ | `mode` | `'dashboard' \| 'portal'` | Controls the navigation behavior of links within the table. Use `'dashboard'` for admin-facing views and `'portal'` for standard customer-facing portals. | `'portal'` |
24
+
25
+ ### Usage Scenarios
26
+
27
+ All examples assume you have a `useSessionContext` hook configured as outlined in the `PaymentProvider` guide.
28
+
29
+ #### 1. Basic Customer View
30
+
31
+ To display the credit transaction history for the currently logged-in user, you can render the component without any specific IDs. It will automatically fetch the user's data from the session context.
32
+
33
+ ```jsx
34
+ import React from 'react';
35
+ import { CreditTransactionsList } from '@blocklet/payment-react/components/history';
36
+ // Assuming useSessionContext is set up according to the PaymentProvider guide
37
+ import { useSessionContext } from '../../contexts/session';
38
+
39
+ export default function UserCreditHistoryPage() {
40
+ const { session } = useSessionContext();
41
+
42
+ // Render the component only when the session is active
43
+ if (!session.user) {
44
+ return <p>Please log in to see your credit history.</p>;
45
+ }
46
+
47
+ return (
48
+ <>
49
+ <h2>My Credit Transactions</h2>
50
+ <CreditTransactionsList pageSize={5} />
51
+ </>
52
+ );
53
+ }
54
+ ```
55
+
56
+ #### 2. Admin View with Filters
57
+
58
+ For an administrative dashboard, you can display transactions for a specific customer by providing their `customer_id`. You can also enable admin-specific columns and the date filter to provide more powerful data exploration tools.
59
+
60
+ ```jsx
61
+ import React from 'react';
62
+ import { CreditTransactionsList } from '@blocklet/payment-react/components/history';
63
+ // Assuming useSessionContext is set up according to the PaymentProvider guide
64
+ import { useSessionContext } from '../../contexts/session';
65
+
66
+ export default function AdminCustomerCreditHistory({ customerId }) {
67
+ const { session } = useSessionContext();
68
+ const isAdmin = ['owner', 'admin'].includes(session?.user?.role || '');
69
+
70
+ if (!isAdmin) {
71
+ return <p>Access Denied.</p>;
72
+ }
73
+
74
+ return (
75
+ <>
76
+ <h2>Credit Transactions for Customer {customerId}</h2>
77
+ <CreditTransactionsList
78
+ customer_id={customerId}
79
+ showAdminColumns={true}
80
+ showTimeFilter={true}
81
+ mode="dashboard"
82
+ />
83
+ </>
84
+ );
85
+ }
86
+ ```
87
+
88
+ #### 3. Transactions for a Specific Credit Grant
89
+
90
+ When you need to show a detailed usage report for a single credit grant, pass the `credit_grant_id`. This will filter the list to show only the transactions associated with that grant.
91
+
92
+ ```jsx
93
+ import React from 'react';
94
+ import { CreditTransactionsList } from '@blocklet/payment-react/components/history';
95
+
96
+ export default function CreditGrantUsageDetails({ grantId }) {
97
+ return (
98
+ <>
99
+ <h3>Transaction History for this Grant</h3>
100
+ <CreditTransactionsList credit_grant_id={grantId} />
101
+ </>
102
+ );
103
+ }
104
+ ```
105
+
106
+ ### Table Columns
107
+
108
+ The component renders a table with the following columns:
109
+
110
+ - **Amount**: The value of the credit transaction and its unit.
111
+ - **Credit Grant**: A link to the parent credit grant. This column is automatically hidden if the list is already filtered by a `credit_grant_id`.
112
+ - **Description**: Provides context for the transaction, such as the associated subscription or usage event.
113
+ - **Meter Event** (Admin Only): A link to the specific billing meter event that triggered the transaction. This is only visible when `showAdminColumns` is `true` and the user is an admin.
114
+ - **Date**: The timestamp indicating when the transaction was created.
115
+
116
+ After displaying credit usage, you might want to show an overview of all credit grants. To do this, you can use the [`CreditGrantsList`](./components-history-credit-grants-list.md) component.
@@ -0,0 +1,104 @@
1
+ # CustomerInvoiceList
2
+
3
+ The `CustomerInvoiceList` component renders a history of invoices for a specific customer or subscription. It supports two display formats: a compact list grouped by date (`list`) and a detailed, paginated table (`table`). The component can also display a 'Pay' button for open invoices, initiating the payment flow when clicked.
4
+
5
+ To function correctly, especially for payment actions and real-time updates, this component must be wrapped within a `PaymentProvider`. For details on setting up the provider and the `useSessionContext` hook, please refer to the [PaymentProvider documentation](./providers-payment-provider.md).
6
+
7
+ ## Props
8
+
9
+ | Prop | Type | Description | Default |
10
+ | --- | --- | --- | --- |
11
+ | `customer_id` | `string` | The ID of the customer whose invoices are to be displayed. | `''` |
12
+ | `subscription_id` | `string` | The ID of the subscription for which to display invoices. | `''` |
13
+ | `currency_id` | `string` | Filters invoices by a specific currency ID. | `''` |
14
+ | `include_staking` | `boolean` | If `true`, includes staking-related invoices in the list. | `false` |
15
+ | `include_return_staking` | `boolean` | If `true`, includes invoices for returned stakes. | `false` |
16
+ | `include_recovered_from` | `boolean` | If `true`, includes invoices that were recovered from bad debt. | `false` |
17
+ | `status` | `string` | A comma-separated string of invoice statuses to display (e.g., 'open,paid,uncollectible,void'). | `'open,paid,uncollectible'` |
18
+ | `pageSize` | `number` | The number of invoices to display per page. | `10` |
19
+ | `target` | `string` | The target attribute for invoice links (e.g., `_self`, `_blank`). | `'_self'` |
20
+ | `action` | `string` | If set (e.g., to `'pay'`), a 'Pay' button is rendered for open or uncollectible invoices, triggering the payment flow on click. | `''` |
21
+ | `type` | `'list'` \| `'table'` | Determines the rendering mode. `'list'` groups invoices by date, while `'table'` shows a detailed data grid. | `'list'` |
22
+ | `onTableDataChange` | `(newData, oldData) => void` | A callback function that fires when the invoice data is loaded or refreshed. | `() => {}` |
23
+ | `relatedSubscription` | `boolean` | When `type` is `'table'`, setting this to `true` adds a column showing the subscription related to each invoice. | `false` |
24
+
25
+ ## Usage Scenarios
26
+
27
+ ### Basic Invoice History
28
+
29
+ To display a simple list of invoices for a particular subscription, set the `subscription_id` and use the default `type='list'`. This mode is ideal for a quick overview of past transactions.
30
+
31
+ ```tsx
32
+ import { PaymentProvider, CustomerInvoiceList } from '@blocklet/payment-react';
33
+ import { useSessionContext } from '../hooks/session'; // Your local session context hook
34
+
35
+ function InvoiceHistoryPage({ subscriptionId }) {
36
+ const { session, connectApi } = useSessionContext();
37
+
38
+ return (
39
+ <PaymentProvider session={session} connect={connectApi}>
40
+ <h2>Invoice History</h2>
41
+ <CustomerInvoiceList
42
+ subscription_id={subscriptionId}
43
+ status="paid,void"
44
+ />
45
+ </PaymentProvider>
46
+ );
47
+ }
48
+ ```
49
+
50
+ ### Detailed Invoice Table
51
+
52
+ For a more detailed view, use `type='table'`. This mode provides pagination and multiple columns of data, making it suitable for dashboards or customer management pages. You can also add the `relatedSubscription` column for customers with multiple subscriptions.
53
+
54
+ ```tsx
55
+ import { PaymentProvider, CustomerInvoiceList } from '@blocklet/payment-react';
56
+ import { useSessionContext } from '../hooks/session'; // Your local session context hook
57
+
58
+ function CustomerDashboard({ customerId }) {
59
+ const { session, connectApi } = useSessionContext();
60
+
61
+ return (
62
+ <PaymentProvider session={session} connect={connectApi}>
63
+ <h3>All Invoices</h3>
64
+ <CustomerInvoiceList
65
+ customer_id={customerId}
66
+ type="table"
67
+ pageSize={20}
68
+ include_staking={true}
69
+ relatedSubscription={true}
70
+ status="open,paid,uncollectible,void"
71
+ />
72
+ </PaymentProvider>
73
+ );
74
+ }
75
+ ```
76
+
77
+ ### Invoices with Payment Action
78
+
79
+ By setting the `action` prop, you can enable a 'Pay' button for any invoices that are `open` or `uncollectible`. Clicking this button will open the payment modal provided by `PaymentProvider` to complete the transaction.
80
+
81
+ ```tsx
82
+ import { PaymentProvider, CustomerInvoiceList } from '@blocklet/payment-react';
83
+ import { useSessionContext } from '../hooks/session'; // Your local session context hook
84
+
85
+ function PayInvoices({ customerId }) {
86
+ const { session, connectApi } = useSessionContext();
87
+
88
+ return (
89
+ <PaymentProvider session={session} connect={connectApi}>
90
+ <h3>Outstanding Invoices</h3>
91
+ <CustomerInvoiceList
92
+ customer_id={customerId}
93
+ status="open,uncollectible"
94
+ action="pay" // This enables the "Pay" button
95
+ type="table"
96
+ />
97
+ </PaymentProvider>
98
+ );
99
+ }
100
+ ```
101
+
102
+ ### Real-time Updates
103
+
104
+ The component automatically subscribes to the `invoice.paid` WebSocket event. When a customer successfully pays an invoice, the list will refresh in real-time to reflect the new `paid` status without requiring a page reload. This ensures that the invoice data is always up-to-date.
@@ -0,0 +1,65 @@
1
+ # CustomerPaymentList
2
+
3
+ The `CustomerPaymentList` component renders a detailed history of a customer's payments. It is designed for efficiency, featuring infinite scrolling to handle large numbers of transactions without compromising performance. Payments are automatically grouped by date for easy navigation and review.
4
+
5
+ ## Props
6
+
7
+ | Prop | Type | Description | Required |
8
+ |---|---|---|---|
9
+ | `customer_id` | `string` | The ID of the customer whose payment history should be displayed. | Yes |
10
+
11
+ ## Usage Example
12
+
13
+ To use the `CustomerPaymentList`, you must provide a `customer_id`. The component handles all the logic for fetching, paginating, and displaying the payment data. It must be wrapped within a `PaymentProvider` to function correctly.
14
+
15
+ ```tsx
16
+ import { PaymentProvider, CustomerPaymentList } from '@blocklet/payment-react';
17
+ import { useSessionContext } from '../hooks/session'; // This is your app's custom session hook
18
+ import { Box, Typography } from '@mui/material';
19
+
20
+ function CustomerProfilePage() {
21
+ // Get session and connectApi from your application's session context.
22
+ const { session, connectApi } = useSessionContext();
23
+
24
+ // The customer ID would typically be the DID of the logged-in user.
25
+ const customerDid = session?.user?.did;
26
+
27
+ if (!session || !customerDid) {
28
+ return <Typography>Please log in to view payment history.</Typography>;
29
+ }
30
+
31
+ return (
32
+ <PaymentProvider session={session} connect={connectApi}>
33
+ <Box sx={{ p: 3 }}>
34
+ <Typography variant="h5" gutterBottom>
35
+ Payment History
36
+ </Typography>
37
+ <CustomerPaymentList customer_id={customerDid} />
38
+ </Box>
39
+ </PaymentProvider>
40
+ );
41
+ }
42
+
43
+ export default CustomerProfilePage;
44
+ ```
45
+
46
+ In the example above, `useSessionContext` is a custom hook responsible for providing your application's session state. For detailed instructions on how to set up the `PaymentProvider` and create a session context, please refer to our guide on the [PaymentProvider](./providers-payment-provider.md).
47
+
48
+ ## Features
49
+
50
+ - **Automatic Pagination**: The component automatically fetches and renders payments in pages. A "Load More" button appears when more transactions are available, allowing users to load history on demand.
51
+
52
+ - **Date-Based Grouping**: To improve readability, all payments are grouped under the date they were created, making it easy to find transactions from a specific day.
53
+
54
+ - **Detailed Payment Information**: Each row in the list provides key details about the transaction:
55
+ - **Date & Time**: The exact creation time of the payment.
56
+ - **Amount**: The total amount received, formatted with the correct currency symbol.
57
+ - **Status**: The current status of the payment (e.g., `succeeded`, `processing`) shown with a colored indicator using the `Status` component.
58
+ - **Description**: The description associated with the payment intent.
59
+ - **Transaction Link**: A direct link to the relevant blockchain explorer for on-chain transactions, if applicable.
60
+
61
+ - **Loading and Empty States**: A loading indicator is displayed while the initial payment data is being fetched. If the customer has no payment history, a clear message is shown instead of an empty list.
62
+
63
+ ## Related Components
64
+
65
+ For displaying a customer's invoice history, which is often related to their payment history, see the [`CustomerInvoiceList`](./components-history-invoice-list.md) component.
@@ -0,0 +1,92 @@
1
+ # History Components
2
+
3
+ The History Components are a suite of tools designed to give customers a clear and detailed view of their financial interactions. They are essential for building transparent and user-friendly account management sections, such as a customer portal or a billing history page. These components fetch and display data related to invoices, payments, and credit balances, providing a complete historical record.
4
+
5
+ ```d2
6
+ direction: down
7
+
8
+ "Customer Portal" -> "Billing Section"
9
+
10
+ "Billing Section": {
11
+ "Invoices": "CustomerInvoiceList"
12
+ "Payments": "CustomerPaymentList"
13
+ "Credits": {
14
+ "Grants": "CreditGrantsList"
15
+ "Usage": "CreditTransactionsList"
16
+ }
17
+ }
18
+ ```
19
+
20
+ This section provides an overview of the components available for displaying historical data. Each component is designed to be easily integrated into your application to provide a specific piece of a customer's history.
21
+
22
+ <x-cards data-columns="2">
23
+ <x-card data-title="CustomerInvoiceList" data-icon="lucide:receipt" data-href="/components/history/invoice-list">
24
+ Renders a list of a customer's invoices, including key details like the amount, status, date, and a link to view the full invoice. It supports both a simple list view and a more detailed table view.
25
+ </x-card>
26
+ <x-card data-title="CustomerPaymentList" data-icon="lucide:credit-card" data-href="/components/history/payment-list">
27
+ Use this component to display a complete history of payments made by a customer. It lists each payment with its amount, status, date, and a link to the corresponding transaction on the blockchain, if applicable.
28
+ </x-card>
29
+ <x-card data-title="CreditGrantsList" data-icon="lucide:gift" data-href="/components/history/credit-grants-list">
30
+ The `CreditGrantsList` component shows all credit grants a customer has received. It details the status, remaining balance, and validity period of each grant, which is useful for managing promotional credits or prepaid balances.
31
+ </x-card>
32
+ <x-card data-title="CreditTransactionsList" data-icon="lucide:list-ordered" data-href="/components/history/credit-transactions-list">
33
+ To provide a granular view of how credits are used, the `CreditTransactionsList` component logs every transaction that affects a customer's credit balance. This includes credit deductions for service usage and any adjustments.
34
+ </x-card>
35
+ </x-cards>
36
+
37
+ ### Example: Building a Billing Page
38
+
39
+ You can easily combine these components using a tabbed interface to create a complete billing history section for your users. Most history components rely on `PaymentProvider` to access the DID Connect instance for actions like paying an invoice.
40
+
41
+ The following example shows how to set up a complete billing page. It assumes you have a local `session.js` or `session.ts` file that exports `useSessionContext` for your DID Connect integration. For more details on setting up the provider, see the [PaymentProvider documentation](./providers-payment-provider.md).
42
+
43
+ ```jsx
44
+ import React from 'react';
45
+ import { Tabs, Tab, Box, Typography } from '@mui/material';
46
+ import { PaymentProvider } from '@blocklet/payment-react/lib/contexts/payment';
47
+ import { useSessionContext } from '../contexts/session'; // Your local session context
48
+
49
+ import CustomerInvoiceList from '@blocklet/payment-react/lib/history/invoice/list';
50
+ import CustomerPaymentList from '@blocklet/payment-react/lib/history/payment/list';
51
+ import CreditGrantsList from '@blocklet/payment-react/lib/history/credit/grants-list';
52
+ import CreditTransactionsList from '@blocklet/payment-react/lib/history/credit/transactions-list';
53
+
54
+ function BillingHistoryPage() {
55
+ const { session, connect } = useSessionContext();
56
+ const [tab, setTab] = React.useState(0);
57
+
58
+ const handleChange = (event, newValue) => {
59
+ setTab(newValue);
60
+ };
61
+
62
+ // The customerId is the user's DID from the session.
63
+ const customerId = session.user?.did;
64
+
65
+ if (!session.ready || !customerId) {
66
+ return <Typography>Please log in to view your billing history.</Typography>;
67
+ }
68
+
69
+ return (
70
+ <PaymentProvider connect={connect}>
71
+ <Box sx={{ width: '100%' }}>
72
+ <Tabs value={tab} onChange={handleChange} aria-label="billing history tabs">
73
+ <Tab label="Invoices" />
74
+ <Tab label="Payments" />
75
+ <Tab label="Credit Grants" />
76
+ <Tab label="Credit Usage" />
77
+ </Tabs>
78
+ <Box sx={{ p: 3 }}>
79
+ {tab === 0 && <CustomerInvoiceList customer_id={customerId} type="table" />}
80
+ {tab === 1 && <CustomerPaymentList customer_id={customerId} />}
81
+ {tab === 2 && <CreditGrantsList customer_id={customerId} />}
82
+ {tab === 3 && <CreditTransactionsList customer_id={customerId} />}
83
+ </Box>
84
+ </Box>
85
+ </PaymentProvider>
86
+ );
87
+ }
88
+ ```
89
+
90
+ By using these components, you can build a comprehensive and professional billing history section. This not only improves user experience but also reduces support inquiries by providing customers with self-service access to their data.
91
+
92
+ After implementing history views, you may want to explore advanced topics like customization and theming. Continue to the next section to learn more in our [Guides](./guides.md).
@@ -0,0 +1,150 @@
1
+ # AddressForm
2
+
3
+ The `AddressForm` component provides a pre-built UI for collecting billing address details. It includes fields for address line 1, city, state, postal code, and country, with built-in validation that adapts based on the selected country.
4
+
5
+ This component is designed to work seamlessly within the context of `react-hook-form`.
6
+
7
+ ## Props
8
+
9
+ | Prop | Type | Description | Required |
10
+ | --- | --- | --- | :---: |
11
+ | `mode` | `string` | Determines the form's behavior. Set to `'required'` to display the full address form. | Yes |
12
+ | `stripe` | `boolean` | If `true` and `mode` is not `'required'`, it displays a simplified form with only postal code and country. | Yes |
13
+ | `sx` | `SxProps` | Custom MUI styles to be applied to the root `Stack` component. | No |
14
+ | `fieldValidation` | `Record<string, any>` | An object for providing custom validation rules, such as regex patterns, for specific fields. | No |
15
+ | `errorPosition` | `'right'` \| `'bottom'` | Specifies the position of validation error messages relative to the input fields. Defaults to `'right'`. | No |
16
+
17
+ ## Integration with React Hook Form
18
+
19
+ `AddressForm` uses `useFormContext` and therefore must be a descendant of a `FormProvider` component from `react-hook-form`. In a typical application, a higher-level component like `CheckoutForm` would wrap your feature and provide this context automatically.
20
+
21
+ Note: The following examples assume you have set up `PaymentProvider` and a local `useSessionContext` hook as described in the [PaymentProvider documentation](./providers-payment-provider.md).
22
+
23
+ ## Usage Scenarios
24
+
25
+ ### Complete Address Form
26
+
27
+ To collect a full billing address, set the `mode` prop to `'required'`. This will render all address fields as mandatory.
28
+
29
+ ```jsx
30
+ import { FormProvider, useForm } from 'react-hook-form';
31
+ import { AddressForm } from '@blocklet/payment-react';
32
+ import { Button, Stack } from '@mui/material';
33
+ import { useSessionContext } from '../hooks/session'; // Adjust path to your session hook
34
+
35
+ export default function FullAddressFormExample() {
36
+ // Standard context setup. Not used in this specific form but required for consistency.
37
+ const { session, connectApi } = useSessionContext();
38
+
39
+ const methods = useForm({
40
+ mode: 'onTouched',
41
+ defaultValues: {
42
+ billing_address: {
43
+ line1: '',
44
+ city: '',
45
+ state: '',
46
+ postal_code: '',
47
+ country: 'US',
48
+ },
49
+ },
50
+ });
51
+
52
+ const onSubmit = (data) => {
53
+ alert('Form Submitted! Check console for data.');
54
+ console.log('Billing Address:', data.billing_address);
55
+ };
56
+
57
+ return (
58
+ <FormProvider {...methods}>
59
+ <form onSubmit={methods.handleSubmit(onSubmit)}>
60
+ <Stack spacing={2}>
61
+ <AddressForm mode="required" stripe={false} errorPosition="bottom" />
62
+ <Button type="submit" variant="contained">
63
+ Submit Address
64
+ </Button>
65
+ </Stack>
66
+ </form>
67
+ </FormProvider>
68
+ );
69
+ }
70
+ ```
71
+
72
+ ### Simplified Stripe Form
73
+
74
+ In some payment flows, particularly with Stripe, only the postal code and country might be required for verification. To render this simplified version, ensure `mode` is not `'required'` and set the `stripe` prop to `true`.
75
+
76
+ ```jsx
77
+ import { FormProvider, useForm } from 'react-hook-form';
78
+ import { AddressForm } from '@blocklet/payment-react';
79
+ import { Button, Stack } from '@mui/material';
80
+ import { useSessionContext } from '../hooks/session'; // Adjust path to your session hook
81
+
82
+ export default function StripeAddressFormExample() {
83
+ // Standard context setup. Not used in this specific form but required for consistency.
84
+ const { session, connectApi } = useSessionContext();
85
+
86
+ const methods = useForm({
87
+ mode: 'onTouched',
88
+ defaultValues: {
89
+ billing_address: {
90
+ postal_code: '',
91
+ country: 'US',
92
+ },
93
+ },
94
+ });
95
+
96
+ const onSubmit = (data) => {
97
+ alert('Form Submitted! Check console for data.');
98
+ console.log('Billing Info:', data.billing_address);
99
+ };
100
+
101
+ return (
102
+ <FormProvider {...methods}>
103
+ <form onSubmit={methods.handleSubmit(onSubmit)}>
104
+ <Stack spacing={2}>
105
+ <AddressForm mode="optional" stripe={true} errorPosition="bottom" />
106
+ <Button type="submit" variant="contained">
107
+ Submit
108
+ </Button>
109
+ </Stack>
110
+ </form>
111
+ </FormProvider>
112
+ );
113
+ }
114
+ ```
115
+
116
+ ## Validation
117
+
118
+ `AddressForm` handles validation for required fields automatically. It also includes special validation logic for postal codes.
119
+
120
+ ### Postal Code Validation
121
+
122
+ The postal code field is dynamically validated based on the selected country. The component uses the `validator.js` library to check if the postal code format is valid for a list of supported countries. For countries not on the supported list, a generic validation is applied.
123
+
124
+ ### Custom Validation
125
+
126
+ You can extend the default validation by passing a `fieldValidation` object. This allows you to specify custom regex patterns and error messages for any address field.
127
+
128
+ For example, to add a pattern validation for the state field to accept only two-letter abbreviations:
129
+
130
+ ```jsx
131
+ const customValidation = {
132
+ 'billing_address.state': {
133
+ pattern: '^[A-Z]{2}$',
134
+ pattern_message: {
135
+ en: 'State must be a 2-letter abbreviation.',
136
+ // Add other locales as needed
137
+ },
138
+ },
139
+ };
140
+
141
+ <AddressForm
142
+ mode="required"
143
+ stripe={false}
144
+ fieldValidation={customValidation}
145
+ />
146
+ ```
147
+
148
+ ## Related Components
149
+
150
+ - **[CountrySelect](./components-ui-form-elements-country-select.md)**: The `AddressForm` uses this component internally to provide a searchable, user-friendly country dropdown with flags.
@@ -0,0 +1,105 @@
1
+ # CountrySelect
2
+
3
+ The `CountrySelect` component is a dropdown for selecting a country, featuring an integrated search filter, country flags, and a responsive design that adapts to desktop and mobile views. It is built to work seamlessly within forms managed by `react-hook-form` and must be wrapped in a `FormProvider` to function correctly.
4
+
5
+ ## Props
6
+
7
+ The component accepts the following props:
8
+
9
+ | Prop | Type | Required | Default | Description |
10
+ | :--- | :--- | :--- | :--- | :--- |
11
+ | `value` | `CountryIso2` | Yes | | The ISO2 code of the currently selected country (e.g., 'us'). |
12
+ | `onChange` | `(value: CountryIso2) => void` | Yes | | Callback function invoked when a country is selected. |
13
+ | `name` | `string` | Yes | | The name of the input field, used for integration with `react-hook-form`. |
14
+ | `sx` | `SxProps` | No | `{}` | Custom styles applied to the root element using the MUI `sx` prop. |
15
+ | `showDialCode` | `boolean` | No | `false` | If `true`, the country's dial code is displayed next to its name in the list. |
16
+
17
+ ## Basic Usage
18
+
19
+ Here is a basic example of how to use the `CountrySelect` component. It must be wrapped in a `FormProvider` from `react-hook-form` because it internally uses `useFormContext` to manage form state.
20
+
21
+ ```jsx
22
+ import { useState } from 'react';
23
+ import { FormProvider, useForm } from 'react-hook-form';
24
+ import { CountrySelect } from '@blocklet/payment-react';
25
+ import { Box } from '@mui/material';
26
+ import type { CountryIso2 } from 'react-international-phone';
27
+
28
+ function BasicCountrySelect() {
29
+ const [selectedCountry, setSelectedCountry] = useState<CountryIso2>('us');
30
+ const methods = useForm({
31
+ defaultValues: {
32
+ country: 'us',
33
+ },
34
+ });
35
+
36
+ const handleCountryChange = (country: CountryIso2) => {
37
+ setSelectedCountry(country);
38
+ console.log('Selected Country:', country);
39
+ };
40
+
41
+ return (
42
+ <FormProvider {...methods}>
43
+ <Box sx={{ maxWidth: 300 }}>
44
+ <CountrySelect
45
+ name="country"
46
+ value={selectedCountry}
47
+ onChange={handleCountryChange}
48
+ />
49
+ </Box>
50
+ </FormProvider>
51
+ );
52
+ }
53
+
54
+ export default BasicCountrySelect;
55
+ ```
56
+
57
+ ## Features
58
+
59
+ ### Search and Filtering
60
+ The dropdown includes a search field at the top of the list, allowing users to filter countries by name, two-letter ISO code, or dial code (e.g., `+1`). This makes it easy to find a specific country in the extensive list.
61
+
62
+ ### Responsive Design
63
+ The component automatically adapts its UI based on the viewport. On desktop devices, it renders as a traditional dropdown menu. On mobile devices, it presents a full-width bottom-sheet dialog, providing a more native and touch-friendly user experience.
64
+
65
+ ### Keyboard Accessibility
66
+ `CountrySelect` is fully navigable using the keyboard, enhancing accessibility:
67
+ - **ArrowDown / ArrowUp / Tab**: Navigate through the list of countries.
68
+ - **Enter**: Select the currently focused country and close the dropdown.
69
+ - **Escape**: Close the dropdown without making a selection.
70
+
71
+ ## Customization
72
+
73
+ ### Displaying the Dial Code
74
+
75
+ To display the phone dial code next to each country, set the `showDialCode` prop to `true`. This is particularly useful when pairing `CountrySelect` with the [`PhoneInput`](./components-ui-form-elements-phone-input.md) component to build a complete international phone number input.
76
+
77
+ ```jsx
78
+ import { useState } from 'react';
79
+ import { FormProvider, useForm } from 'react-hook-form';
80
+ import { CountrySelect } from '@blocklet/payment-react';
81
+ import { Box } from '@mui/material';
82
+ import type { CountryIso2 } from 'react-international-phone';
83
+
84
+ function CountrySelectWithDialCode() {
85
+ const [country, setCountry] = useState<CountryIso2>('us');
86
+ const methods = useForm({ defaultValues: { country: 'us' } });
87
+
88
+ return (
89
+ <FormProvider {...methods}>
90
+ <Box sx={{ maxWidth: 300 }}>
91
+ <CountrySelect
92
+ name="country"
93
+ value={country}
94
+ onChange={setCountry}
95
+ showDialCode={true}
96
+ />
97
+ </Box>
98
+ </FormProvider>
99
+ );
100
+ }
101
+
102
+ export default CountrySelectWithDialCode;
103
+ ```
104
+
105
+ By combining these features, the `CountrySelect` component offers a robust and user-friendly solution for country input fields in any form.