@blocklet/payment-react 1.20.4 → 1.20.6

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 +7 -7
  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,125 +1,91 @@
1
1
  # Form Elements
2
2
 
3
- The `@blocklet/payment-react` library provides a collection of granular input components for building custom payment and contact information forms. These components come with built-in validation, internationalization support, and a responsive UI, simplifying the process of collecting user data.
3
+ The `@blocklet/payment-react` library provides a collection of granular input components designed to simplify the creation of custom payment and contact information forms. These elements are built with validation and user experience in mind, integrating smoothly with `react-hook-form` to provide a robust and flexible solution for data collection.
4
4
 
5
- This section provides an overview of the key form elements. For detailed props and advanced usage, please refer to the specific documentation for each component linked below.
5
+ Each component is designed to be a self-contained unit, allowing you to compose them into complex forms tailored to your specific requirements. Below is an overview of the available form elements.
6
6
 
7
7
  <x-cards data-columns="2">
8
8
  <x-card data-title="AddressForm" data-icon="lucide:map-pin" data-href="/components/ui/form-elements/address-form">
9
- A pre-built form for collecting billing address details, with validation that adapts to the selected country.
9
+ A pre-built form for collecting billing address details with country-specific validation.
10
10
  </x-card>
11
11
  <x-card data-title="PhoneInput" data-icon="lucide:phone" data-href="/components/ui/form-elements/phone-input">
12
- An international phone number input with an integrated country selector, dial code display, and validation.
12
+ An international phone number input with an integrated country code selector and validation.
13
13
  </x-card>
14
14
  <x-card data-title="CountrySelect" data-icon="lucide:globe" data-href="/components/ui/form-elements/country-select">
15
- A searchable dropdown for selecting a country, complete with flags and a responsive design for mobile and desktop.
15
+ A searchable dropdown for selecting a country, complete with flags and a mobile-friendly UI.
16
16
  </x-card>
17
- <x-card data-title="CurrencySelector" data-icon="lucide:circle-dollar-sign" data-href="/components/ui/form-elements/currency-selector">
18
- A component that allows users to select their preferred payment currency from a list of available options.
17
+ <x-card data-title="CurrencySelector" data-icon="lucide:coins" data-href="/components/ui/form-elements/currency-selector">
18
+ A component that allows users to choose their preferred payment currency from available options.
19
19
  </x-card>
20
20
  </x-cards>
21
21
 
22
- ## Usage Patterns
22
+ ## Common Usage Pattern
23
23
 
24
- Most form elements are designed to work within a `react-hook-form` context, while others can be used as standalone components.
24
+ These form elements are intended to be used within a `FormProvider` from `react-hook-form`. You can compose them to build comprehensive forms that capture all the necessary information for a transaction. While each component has its own set of properties, they share a common integration pattern.
25
25
 
26
- ### Form-Based Components
26
+ Here is a basic example of how you might combine several form elements to create a user information form:
27
27
 
28
- Components like `AddressForm` and `PhoneInput` should be wrapped in a `FormProvider` from `react-hook-form`. This allows them to share form state, validation, and submission logic seamlessly.
29
-
30
- Here is an example of how to combine them into a single form:
31
-
32
- ```jsx
28
+ ```jsx MyCustomForm.tsx icon=logos:react
33
29
  import { FormProvider, useForm } from 'react-hook-form';
34
- import { AddressForm, PhoneInput } from '@blocklet/payment-react';
35
- import { Button } from '@mui/material';
36
- import { getPhoneUtil } from '@blocklet/payment-react/libs/phone-validator';
30
+ import { AddressForm, PhoneInput, CurrencySelector } from '@blocklet/payment-react';
31
+ import { Button, Stack } from '@mui/material';
32
+
33
+ // Assume `availableCurrencies` is fetched from your backend
34
+ const availableCurrencies = [
35
+ {
36
+ id: 'usd_xxx',
37
+ name: 'USD',
38
+ symbol: 'USD',
39
+ logo: 'url/to/usd_logo.png',
40
+ method: { id: 'stripe', name: 'Stripe' },
41
+ },
42
+ // ... other currencies
43
+ ];
37
44
 
38
- function MyContactForm() {
45
+ function MyCustomForm() {
39
46
  const methods = useForm({
40
47
  defaultValues: {
41
- phone: '',
48
+ currency: 'usd_xxx',
49
+ phone_number: '',
42
50
  billing_address: {
43
51
  line1: '',
44
52
  city: '',
45
53
  state: '',
46
54
  postal_code: '',
47
- country: 'us',
55
+ country: 'US', // Use ISO2 code
48
56
  },
49
57
  },
50
58
  });
51
59
 
52
- const validatePhoneNumber = async (phone) => {
53
- const phoneUtil = await getPhoneUtil();
54
- return phoneUtil.isValid(phone) || 'Invalid phone number';
55
- };
56
-
57
60
  const onSubmit = (data) => {
58
- console.log('Form data:', data);
61
+ console.log('Form data submitted:', data);
59
62
  };
60
63
 
61
64
  return (
62
65
  <FormProvider {...methods}>
63
66
  <form onSubmit={methods.handleSubmit(onSubmit)}>
64
- <AddressForm mode="required" stripe={false} />
65
- <PhoneInput
66
- name="phone"
67
- label="Phone Number"
68
- rules={{ validate: validatePhoneNumber }}
69
- />
70
- <Button type="submit" variant="contained" sx={{ mt: 2 }}>
71
- Submit
72
- </Button>
67
+ <Stack spacing={2}>
68
+ <CurrencySelector
69
+ value={methods.watch('currency')}
70
+ currencies={availableCurrencies}
71
+ onChange={(currencyId) => methods.setValue('currency', currencyId)}
72
+ />
73
+ <PhoneInput name="phone_number" label="Phone Number" required />
74
+ <AddressForm mode="required" stripe={false} />
75
+ <Button type="submit" variant="contained">
76
+ Submit
77
+ </Button>
78
+ </Stack>
73
79
  </form>
74
80
  </FormProvider>
75
81
  );
76
82
  }
77
83
  ```
78
84
 
79
- ### Standalone Components
80
-
81
- Components like `CurrencySelector` are self-contained and manage their state via props and callbacks, so they don't need to be inside a `FormProvider`.
82
-
83
- ```jsx
84
- import { CurrencySelector } from '@blocklet/payment-react';
85
- import { useState } from 'react';
86
-
87
- // Example currency data structure
88
- const sampleCurrencies = [
89
- {
90
- id: 'usd_credit_card',
91
- name: 'USD',
92
- symbol: '$',
93
- logo: 'https://example.com/usd-logo.png',
94
- method: { id: 'card', name: 'Credit Card' },
95
- },
96
- {
97
- id: 'eth_mainnet',
98
- name: 'Ethereum',
99
- symbol: 'ETH',
100
- logo: 'https://example.com/eth-logo.png',
101
- method: { id: 'crypto', name: 'Ethereum Network' },
102
- },
103
- ];
104
-
105
- function MyCurrencyComponent() {
106
- const [selectedCurrency, setSelectedCurrency] = useState('usd_credit_card');
107
-
108
- const handleChange = (currencyId, methodId) => {
109
- setSelectedCurrency(currencyId);
110
- console.log('Selected payment method:', methodId);
111
- };
112
-
113
- return (
114
- <CurrencySelector
115
- currencies={sampleCurrencies}
116
- value={selectedCurrency}
117
- onChange={handleChange}
118
- />
119
- );
120
- }
121
- ```
85
+ In this example, `CurrencySelector`, `PhoneInput`, and `AddressForm` are combined within a single form. `CurrencySelector` is used as a controlled component tied to the form's state, while `PhoneInput` and `AddressForm` are uncontrolled components that automatically register their fields and validation rules with the `react-hook-form` context.
122
86
 
123
87
  ## Next Steps
124
88
 
125
- Now that you have an overview of the individual form elements, you can explore their detailed documentation for advanced configurations. For building a complete payment experience, consider using higher-level components like [`CheckoutForm`](./components-checkout-checkout-form.md), which integrate these elements into a complete and managed flow.
89
+ To learn more about the specific properties and implementation details of each component, please explore their individual documentation pages.
90
+
91
+ Start with the [AddressForm](./components-ui-form-elements-address-form.md) to see how to collect billing information.
@@ -1,157 +1,109 @@
1
1
  # PaymentSummary
2
2
 
3
- The `PaymentSummary` component displays a detailed overview of an order within the checkout flow. It lists all line items, shows any applicable trial periods or staking requirements, and calculates the total amount due. It is designed to give customers a clear and transparent breakdown of their purchase before they complete the payment.
3
+ The `PaymentSummary` component is a crucial UI element for any checkout process. It provides a detailed breakdown of the order, including all line items, trial period information, staking requirements, and the final total amount. It's designed to be responsive and adapts its layout for mobile devices.
4
4
 
5
- This component works in conjunction with `ProductItem` to render individual items and can adapt its display for various scenarios, including cross-sells, upsells, and donations.
5
+ This component works in tandem with `ProductItem` and `ProductDonation` to render each item in the cart, and it handles user interactions like applying cross-sells or changing quantities.
6
6
 
7
7
  ## Props
8
8
 
9
- The `PaymentSummary` component accepts the following props to customize its behavior and the information it displays.
10
-
11
- | Prop | Type | Description |
12
- |---|---|---|
13
- | `items` | `TLineItemExpanded[]` | **Required.** An array of line item objects to be displayed in the summary. |
14
- | `currency` | `TPaymentCurrency` | **Required.** The currency object used for formatting amounts. |
15
- | `trialInDays` | `number` | The number of days for a trial period. Defaults to `0`. |
16
- | `trialEnd` | `number` | A Unix timestamp indicating when the trial ends. |
17
- | `billingThreshold` | `number` | The billing threshold for staking calculations. |
18
- | `showStaking` | `boolean` | If `true`, staking information will be calculated and displayed. Defaults to `false`. |
19
- | `onUpsell` | `(from: string, to: string) => void` | Callback function triggered when a user accepts an upsell offer. |
20
- | `onDownsell` | `(from: string) => void` | Callback function triggered when a user reverts an upsell offer. |
21
- | `onQuantityChange` | `(itemId: string, quantity: number) => void` | Callback function for when the quantity of an item is changed. |
22
- | `onChangeAmount` | `(amount: number) => void` | Callback function for when a custom donation amount is changed. |
23
- | `onApplyCrossSell` | `(crossSellId: string) => void` | Callback function to add a cross-sell item to the cart. |
24
- | `onCancelCrossSell` | `() => void` | Callback function to remove a cross-sell item from the cart. |
25
- | `checkoutSessionId` | `string` | The ID of the current checkout session, used to fetch available cross-sell offers. |
26
- | `crossSellBehavior` | `'required' \| 'optional'` | Defines the behavior of the cross-sell offer. Defaults to `''` (optional). |
27
- | `donationSettings` | `DonationSettings` | Configuration object for donation items. |
28
- | `action` | `string` | A custom title to display at the top of the summary box (e.g., "Renew Subscription"). Defaults to "Order Summary". |
29
- | `completed` | `boolean` | If `true`, disables interactive elements like quantity adjustments, as the checkout is complete. Defaults to `false`. |
9
+ The `PaymentSummary` component accepts the following props to customize its behavior and display:
10
+
11
+ | Prop | Type | Required | Description |
12
+ | --- | --- | --- | --- |
13
+ | `items` | `TLineItemExpanded[]` | Yes | An array of line items to be displayed in the summary. |
14
+ | `currency` | `TPaymentCurrency` | Yes | The currency object for formatting amounts. |
15
+ | `trialInDays` | `number` | Yes | The number of trial days for recurring subscriptions. |
16
+ | `billingThreshold` | `number` | Yes | The billing threshold amount. Used in staking calculation if applicable. |
17
+ | `trialEnd` | `number` | No | A Unix timestamp for when the trial ends. Overrides `trialInDays`. |
18
+ | `showStaking` | `boolean` | No | If `true`, displays staking details. Defaults to `false`. |
19
+ | `onUpsell` | `(from: string, to: string) => void` | No | Callback function when a user accepts an upsell offer. |
20
+ | `onDownsell` | `(from: string) => void` | No | Callback function when a user reverts an upsell offer. |
21
+ | `onQuantityChange` | `(itemId: string, quantity: number) => void` | No | Callback function when the quantity of an item is changed. |
22
+ | `onChangeAmount` | `(itemId: string, amount: string) => void` | No | Callback for changing the amount of a custom-amount item, like a donation. |
23
+ | `onApplyCrossSell` | `(crossSellId: string) => void` | No | Callback function when a user adds a cross-sell item. |
24
+ | `onCancelCrossSell` | `() => void` | No | Callback function when a user removes a cross-sell item. |
25
+ | `checkoutSessionId` | `string` | No | The ID of the checkout session, used to fetch potential cross-sell items. |
26
+ | `crossSellBehavior` | `string` | No | Defines the behavior of the cross-sell item (e.g., `'required'`). |
27
+ | `donationSettings` | `DonationSettings` | No | Configuration for donation items. |
28
+ | `action` | `string` | No | A custom title for the summary section, replacing "Order Summary". |
29
+ | `completed` | `boolean` | No | If `true`, disables interactive elements like quantity adjustment. Defaults to `false`. |
30
30
 
31
31
  ## Usage
32
32
 
33
- The `PaymentSummary` component is typically placed within a checkout page to provide a persistent view of the order details. It must be wrapped by a `PaymentProvider` to access necessary context.
33
+ The `PaymentSummary` component should be placed within a `PaymentProvider` and is typically used as part of a larger checkout form. You need to provide it with the line items and currency information.
34
34
 
35
- For details on setting up the provider, please see the [PaymentProvider documentation](./providers-payment-provider.md).
35
+ Here is a basic example of how to integrate the `PaymentSummary` component.
36
36
 
37
- ### Basic Order Summary
38
-
39
- Here is a basic example of rendering a payment summary. The component automatically calculates totals and displays item details based on the `items` and `currency` props.
40
-
41
- ```jsx
42
- // Note: Ensure this component is rendered within a PaymentProvider.
37
+ ```tsx PaymentSummary Example icon=lucide:shopping-cart
43
38
  import React from 'react';
44
- import { PaymentSummary } from '@blocklet/payment-react';
45
-
46
- const items = [
47
- {
48
- price_id: 'price_123',
49
- quantity: 2,
50
- price: {
51
- product: { name: 'Standard Plan', images: ['/logo.png'] },
52
- type: 'recurring',
53
- recurring: { interval: 'month', interval_count: 1 },
54
- unit_amount: '10.00',
55
- },
56
- // other TLineItemExpanded properties...
57
- },
58
- ];
39
+ import { PaymentProvider, PaymentSummary } from '@blocklet/payment-react';
40
+ import { useSessionContext } from '../hooks/session-context'; // Your session context hook
59
41
 
60
- const currency = {
61
- id: 'usd',
42
+ // Mock data for demonstration purposes
43
+ const mockCurrency = {
44
+ id: 'usd_4573516104843264',
62
45
  symbol: '$',
46
+ name: 'USD',
63
47
  decimal: 2,
64
- // other TPaymentCurrency properties...
48
+ isDefault: true,
65
49
  };
66
50
 
67
- function MyCheckoutPage() {
68
- return (
69
- <PaymentSummary
70
- items={items}
71
- currency={currency}
72
- trialInDays={14}
73
- />
74
- );
75
- }
76
- ```
77
-
78
- ### Displaying Staking and Totals
79
-
80
- When `showStaking` is set to `true`, the component calculates and displays the required staking amount separately from the payment amount. The final total combines both values.
81
-
82
- ```jsx
83
- // Note: Ensure this component is rendered within a PaymentProvider.
84
- import React from 'react';
85
- import { PaymentSummary } from '@blocklet/payment-react';
86
-
87
- const recurringItems = [
51
+ const mockItems = [
88
52
  {
89
- price_id: 'price_456',
53
+ id: 'li_1',
54
+ price_id: 'price_1',
90
55
  quantity: 1,
56
+ adjustable_quantity: { enabled: true, minimum: 1, maximum: 10 },
91
57
  price: {
92
- product: { name: 'Pro Plan' },
58
+ id: 'price_1',
93
59
  type: 'recurring',
94
- recurring: { interval: 'year', interval_count: 1, usage_type: 'licensed' },
95
- unit_amount: '100.00',
60
+ recurring: { interval: 'month', interval_count: 1, usage_type: 'licensed' },
61
+ unit_amount: '2000',
62
+ product: {
63
+ name: 'Pro Plan',
64
+ images: [],
65
+ },
96
66
  },
97
67
  },
98
68
  ];
99
- const currency = { id: 'usd', symbol: '$', decimal: 2 };
100
69
 
101
- function StakingCheckoutPage() {
70
+ export default function MyCheckoutPage() {
71
+ const { session, connectApi } = useSessionContext();
72
+
73
+ const handleQuantityChange = (itemId, newQuantity) => {
74
+ console.log(`Item ${itemId} quantity changed to ${newQuantity}`);
75
+ // Here you would typically update your state and refetch checkout info
76
+ };
77
+
102
78
  return (
103
- <PaymentSummary
104
- items={recurringItems}
105
- currency={currency}
106
- showStaking={true}
107
- billingThreshold={50} // Optional: Sets a fixed staking amount
108
- />
79
+ <PaymentProvider session={session} connectApi={connectApi}>
80
+ <PaymentSummary
81
+ items={mockItems}
82
+ currency={mockCurrency}
83
+ trialInDays={14}
84
+ billingThreshold={0}
85
+ showStaking={true}
86
+ onQuantityChange={handleQuantityChange}
87
+ />
88
+ </PaymentProvider>
109
89
  );
110
90
  }
111
91
  ```
112
92
 
113
- ### Handling Cross-Sells
93
+ ### Displaying Staking and Totals
114
94
 
115
- By providing a `checkoutSessionId`, the component can fetch and display cross-sell offers. The `crossSellBehavior` prop determines if the offer is optional or required. User interactions are handled via the `onApplyCrossSell` and `onCancelCrossSell` callbacks.
95
+ If `showStaking` is set to `true`, the component will calculate and display the required staking amount for recurring items. It separates the amount due for immediate payment from the amount required for staking, providing a clear financial summary to the user. The final total combines these amounts.
116
96
 
117
- ```jsx
118
- // Note: Ensure this component is rendered within a PaymentProvider.
119
- import React from 'react';
120
- import { PaymentSummary } from '@blocklet/payment-react';
97
+ ### Handling Trial Periods
121
98
 
122
- const items = [
123
- {
124
- price_id: 'price_123',
125
- quantity: 1,
126
- price: { product: { name: 'Main Product' }, unit_amount: '25.00' },
127
- },
128
- ];
129
- const currency = { id: 'usd', symbol: '$', decimal: 2 };
130
-
131
- function CrossSellCheckoutPage() {
132
- const handleApplyCrossSell = async (crossSellId) => {
133
- console.log('Applying cross-sell:', crossSellId);
134
- // Add logic to update the checkout session via API call
135
- };
99
+ The component clearly communicates trial periods to the user. By passing `trialInDays` or `trialEnd`, a message like "Then $20.00 / month" will be displayed below the total, informing the user about the recurring charges after the trial concludes.
136
100
 
137
- const handleCancelCrossSell = async () => {
138
- console.log('Canceling cross-sell');
139
- // Add logic to update the checkout session via API call
140
- };
101
+ ### Interactive Features
141
102
 
142
- return (
143
- <PaymentSummary
144
- items={items}
145
- currency={currency}
146
- checkoutSessionId="cs_12345"
147
- crossSellBehavior="required"
148
- onApplyCrossSell={handleApplyCrossSell}
149
- onCancelCrossSell={handleCancelCrossSell}
150
- />
151
- );
152
- }
153
- ```
103
+ - **Quantity Adjustment**: If an item has `adjustable_quantity.enabled` set to `true`, the `PaymentSummary` (via its child `ProductItem`) will render controls to increase or decrease the quantity. The `onQuantityChange` callback is triggered upon modification.
104
+ - **Upsell/Downsell**: For products with an upsell configuration, a switch is rendered to allow users to upgrade their plan. The `onUpsell` and `onDownsell` callbacks handle these actions.
105
+ - **Cross-Sell**: If a `checkoutSessionId` is provided, the component can fetch and display suggested cross-sell items. Buttons to add or remove these items trigger the `onApplyCrossSell` and `onCancelCrossSell` callbacks.
154
106
 
155
107
  ### Mobile Responsiveness
156
108
 
157
- On mobile devices, the component automatically renders a collapsible section for the product list to save screen space. The list is initially collapsed if it contains three or more items. This behavior is handled internally using the `useMobile` hook and requires no extra configuration.
109
+ On mobile devices, the list of products is collapsible by default to save space, especially for orders with many items. Users can tap to expand or collapse the list, providing a cleaner and more user-friendly experience on smaller screens.