@blocklet/payment-react 1.18.6 → 1.18.8

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 (70) hide show
  1. package/README.md +394 -341
  2. package/es/checkout/donate.d.ts +29 -4
  3. package/es/checkout/donate.js +193 -95
  4. package/es/components/livemode.js +1 -1
  5. package/es/components/loading-button.d.ts +10 -0
  6. package/es/components/loading-button.js +75 -0
  7. package/es/components/pricing-table.js +2 -3
  8. package/es/components/table.js +1 -1
  9. package/es/index.d.ts +2 -1
  10. package/es/index.js +3 -1
  11. package/es/libs/util.d.ts +1 -0
  12. package/es/libs/util.js +10 -1
  13. package/es/payment/amount.js +1 -1
  14. package/es/payment/form/index.js +14 -12
  15. package/es/payment/form/stripe/form.js +20 -5
  16. package/es/payment/index.js +0 -1
  17. package/es/payment/product-card.js +2 -2
  18. package/es/payment/product-item.js +1 -1
  19. package/es/payment/product-skeleton.js +2 -2
  20. package/es/payment/skeleton/donation.js +1 -1
  21. package/es/payment/skeleton/overview.js +1 -1
  22. package/es/payment/skeleton/payment.js +1 -1
  23. package/es/payment/summary.js +2 -2
  24. package/es/theme/index.js +5 -3
  25. package/es/theme/typography.js +8 -8
  26. package/lib/checkout/donate.d.ts +29 -4
  27. package/lib/checkout/donate.js +197 -136
  28. package/lib/components/livemode.js +1 -1
  29. package/lib/components/loading-button.d.ts +10 -0
  30. package/lib/components/loading-button.js +86 -0
  31. package/lib/components/pricing-table.js +3 -4
  32. package/lib/components/table.js +1 -1
  33. package/lib/index.d.ts +2 -1
  34. package/lib/index.js +8 -0
  35. package/lib/libs/util.d.ts +1 -0
  36. package/lib/libs/util.js +7 -0
  37. package/lib/payment/amount.js +1 -1
  38. package/lib/payment/form/index.js +14 -15
  39. package/lib/payment/form/stripe/form.js +25 -6
  40. package/lib/payment/index.js +0 -1
  41. package/lib/payment/product-card.js +2 -2
  42. package/lib/payment/product-item.js +1 -1
  43. package/lib/payment/product-skeleton.js +2 -2
  44. package/lib/payment/skeleton/donation.js +1 -1
  45. package/lib/payment/skeleton/overview.js +1 -1
  46. package/lib/payment/skeleton/payment.js +1 -1
  47. package/lib/payment/summary.js +4 -4
  48. package/lib/theme/index.js +5 -3
  49. package/lib/theme/typography.js +8 -8
  50. package/package.json +8 -8
  51. package/src/checkout/donate.tsx +209 -128
  52. package/src/components/livemode.tsx +1 -1
  53. package/src/components/loading-button.tsx +100 -0
  54. package/src/components/pricing-table.tsx +3 -3
  55. package/src/components/table.tsx +1 -1
  56. package/src/index.ts +2 -0
  57. package/src/libs/util.ts +11 -1
  58. package/src/payment/amount.tsx +1 -1
  59. package/src/payment/form/index.tsx +65 -60
  60. package/src/payment/form/stripe/form.tsx +21 -6
  61. package/src/payment/index.tsx +0 -1
  62. package/src/payment/product-card.tsx +2 -2
  63. package/src/payment/product-item.tsx +1 -1
  64. package/src/payment/product-skeleton.tsx +2 -2
  65. package/src/payment/skeleton/donation.tsx +1 -1
  66. package/src/payment/skeleton/overview.tsx +1 -1
  67. package/src/payment/skeleton/payment.tsx +1 -1
  68. package/src/payment/summary.tsx +2 -2
  69. package/src/theme/index.tsx +3 -1
  70. package/src/theme/typography.ts +8 -8
@@ -41,6 +41,7 @@ import PhoneInput from './phone';
41
41
  import StripeCheckout from './stripe';
42
42
  import { useMobile } from '../../hooks/mobile';
43
43
  import { validatePhoneNumber } from '../../libs/phone-validator';
44
+ import LoadingButton from '../../components/loading-button';
44
45
 
45
46
  export const waitForCheckoutComplete = async (sessionId: string) => {
46
47
  let result: CheckoutContext;
@@ -212,7 +213,7 @@ export default function PaymentForm({
212
213
  // }, [domSize, theme]);
213
214
 
214
215
  const afterUserLoggedIn = useMemoizedFn(() => {
215
- if (hasDidWallet(session.user)) {
216
+ if (hasDidWallet(session.user) || skipBindWallet) {
216
217
  handleSubmit(onFormSubmit, onFormError)();
217
218
  } else {
218
219
  session.bindWallet(() => {
@@ -239,6 +240,9 @@ export default function PaymentForm({
239
240
 
240
241
  const method = paymentMethods.find((x) => x.id === paymentMethod) as TPaymentMethodExpanded;
241
242
 
243
+ const showForm = session?.user;
244
+ const skipBindWallet = method.type === 'stripe';
245
+
242
246
  const handleConnected = async () => {
243
247
  try {
244
248
  const result = await waitForCheckoutComplete(checkoutSession.id);
@@ -372,6 +376,10 @@ export default function PaymentForm({
372
376
  errorRef.current.scrollIntoView({ behavior: 'smooth' });
373
377
  }
374
378
  if (session?.user) {
379
+ if (skipBindWallet) {
380
+ handleSubmit(onFormSubmit, onFormError)();
381
+ return;
382
+ }
375
383
  if (hasDidWallet(session.user)) {
376
384
  handleSubmit(onFormSubmit, onFormError)();
377
385
  } else {
@@ -492,56 +500,58 @@ export default function PaymentForm({
492
500
  )}
493
501
  </Stack>
494
502
  </Fade>
495
- <Stack
496
- direction="column"
497
- className="cko-payment-form"
498
- id="cko-payment-form"
499
- spacing={0}
500
- ref={!isEmpty(errors) ? (errorRef as any) : undefined}
501
- sx={{ flex: 1, overflow: 'auto', py: 1 }}>
502
- <FormLabel className="base-label">{t('payment.checkout.customer.name')}</FormLabel>
503
- <FormInput
504
- name="customer_name"
505
- variant="outlined"
506
- errorPosition="right"
507
- rules={{
508
- required: t('payment.checkout.required'),
509
- }}
510
- />
511
- <FormLabel className="base-label">{t('payment.checkout.customer.email')}</FormLabel>
512
- <FormInput
513
- name="customer_email"
514
- variant="outlined"
515
- errorPosition="right"
516
- rules={{
517
- required: t('payment.checkout.required'),
518
- validate: (x) => (isEmail(x) ? true : t('payment.checkout.invalid')),
519
- }}
520
- />
521
- {checkoutSession.phone_number_collection?.enabled && (
522
- <>
523
- <FormLabel className="base-label">{t('payment.checkout.customer.phone')}</FormLabel>
524
- <PhoneInput
525
- name="customer_phone"
526
- variant="outlined"
527
- errorPosition="right"
528
- placeholder="Phone number"
529
- rules={{
530
- required: t('payment.checkout.required'),
531
- validate: async (x: string) => {
532
- const isValid = await validatePhoneNumber(x);
533
- return isValid ? true : t('payment.checkout.invalid');
534
- },
535
- }}
536
- />
537
- </>
538
- )}
539
- <AddressForm
540
- mode={checkoutSession.billing_address_collection as string}
541
- stripe={method?.type === 'stripe'}
542
- sx={{ marginTop: '0 !important' }}
543
- />
544
- </Stack>
503
+ {showForm && (
504
+ <Stack
505
+ direction="column"
506
+ className="cko-payment-form"
507
+ id="cko-payment-form"
508
+ spacing={0}
509
+ ref={!isEmpty(errors) ? (errorRef as any) : undefined}
510
+ sx={{ flex: 1, overflow: 'auto', py: 1 }}>
511
+ <FormLabel className="base-label">{t('payment.checkout.customer.name')}</FormLabel>
512
+ <FormInput
513
+ name="customer_name"
514
+ variant="outlined"
515
+ errorPosition="right"
516
+ rules={{
517
+ required: t('payment.checkout.required'),
518
+ }}
519
+ />
520
+ <FormLabel className="base-label">{t('payment.checkout.customer.email')}</FormLabel>
521
+ <FormInput
522
+ name="customer_email"
523
+ variant="outlined"
524
+ errorPosition="right"
525
+ rules={{
526
+ required: t('payment.checkout.required'),
527
+ validate: (x) => (isEmail(x) ? true : t('payment.checkout.invalid')),
528
+ }}
529
+ />
530
+ {checkoutSession.phone_number_collection?.enabled && (
531
+ <>
532
+ <FormLabel className="base-label">{t('payment.checkout.customer.phone')}</FormLabel>
533
+ <PhoneInput
534
+ name="customer_phone"
535
+ variant="outlined"
536
+ errorPosition="right"
537
+ placeholder="Phone number"
538
+ rules={{
539
+ required: t('payment.checkout.required'),
540
+ validate: async (x: string) => {
541
+ const isValid = await validatePhoneNumber(x);
542
+ return isValid ? true : t('payment.checkout.invalid');
543
+ },
544
+ }}
545
+ />
546
+ </>
547
+ )}
548
+ <AddressForm
549
+ mode={checkoutSession.billing_address_collection as string}
550
+ stripe={method?.type === 'stripe'}
551
+ sx={{ marginTop: '0 !important' }}
552
+ />
553
+ </Stack>
554
+ )}
545
555
  </Stack>
546
556
  </Fade>
547
557
  <Divider sx={{ mt: 2.5, mb: 2.5 }} />
@@ -549,28 +559,23 @@ export default function PaymentForm({
549
559
  <Fade in>
550
560
  <Stack className="cko-payment-submit">
551
561
  <Box className="cko-payment-submit-btn">
552
- <Button
562
+ <LoadingButton
553
563
  variant="contained"
554
564
  color="primary"
555
565
  size="large"
556
566
  className="cko-submit-button"
557
567
  onClick={() => {
558
- if (state.submitting || state.paying) {
559
- return;
560
- }
561
568
  onAction();
562
569
  }}
563
570
  fullWidth
571
+ loading={state.submitting || state.paying}
564
572
  disabled={state.stripePaying || !quantityInventoryStatus || !payable}>
565
- {(state.submitting || state.paying) && (
566
- <CircularProgress size={16} sx={{ mr: 0.5, color: 'var(--foregrounds-fg-on-color, #fff)' }} />
567
- )}
568
573
  {state.submitting || state.paying ? t('payment.checkout.processing') : buttonText}
569
- </Button>
574
+ </LoadingButton>
570
575
  </Box>
571
576
 
572
577
  {['subscription', 'setup'].includes(checkoutSession.mode) && (
573
- <Typography sx={{ mt: 2.5, color: 'text.lighter', fontSize: '0.9rem', lineHeight: '1.1rem' }}>
578
+ <Typography sx={{ mt: 2.5, color: 'text.lighter', fontSize: '0.7875rem', lineHeight: '0.9625rem' }}>
574
579
  {t('payment.checkout.confirm', { payee })}
575
580
  </Typography>
576
581
  )}
@@ -2,11 +2,12 @@ import Center from '@arcblock/ux/lib/Center';
2
2
  import Dialog from '@arcblock/ux/lib/Dialog';
3
3
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
4
4
  import type { TCustomer } from '@blocklet/payment-types';
5
- import { LoadingButton } from '@mui/lab';
6
5
  import { CircularProgress, Typography } from '@mui/material';
7
6
  import { styled } from '@mui/system';
8
7
  import { useSetState } from 'ahooks';
9
8
  import { useEffect, useCallback } from 'react';
9
+ import { useMobile } from '../../../hooks/mobile';
10
+ import LoadingButton from '../../../components/loading-button';
10
11
 
11
12
  const { Elements, PaymentElement, useElements, useStripe, loadStripe } = (globalThis as any).__STRIPE_COMPONENTS__;
12
13
 
@@ -124,11 +125,10 @@ function StripeCheckoutForm({
124
125
  {stripe && elements && state.loaded && (
125
126
  <LoadingButton
126
127
  fullWidth
127
- sx={{ mt: 2, mb: 1, borderRadius: 0, fontSize: '1.1rem' }}
128
+ sx={{ mt: 2, mb: 1, borderRadius: 0, fontSize: '0.875rem' }}
128
129
  type="submit"
129
130
  disabled={state.confirming || !state.loaded}
130
131
  loading={state.confirming}
131
- loadingPosition="end"
132
132
  variant="contained"
133
133
  color="primary"
134
134
  size="large">
@@ -171,7 +171,8 @@ export default function StripeCheckout({
171
171
  returnUrl = '',
172
172
  }: StripeCheckoutProps) {
173
173
  const stripePromise = loadStripe(publicKey);
174
- const { t } = useLocaleContext();
174
+ const { isMobile } = useMobile();
175
+ const { t, locale } = useLocaleContext();
175
176
  const [state, setState] = useSetState({
176
177
  open: true,
177
178
  closable: true,
@@ -192,8 +193,22 @@ export default function StripeCheckout({
192
193
  showCloseButton={state.closable}
193
194
  open={state.open}
194
195
  onClose={handleClose}
195
- disableEscapeKeyDown>
196
- <Elements options={{ clientSecret }} stripe={stripePromise}>
196
+ disableEscapeKeyDown
197
+ sx={{
198
+ '.StripeElement': {
199
+ minWidth: isMobile ? '100%' : '500px',
200
+ py: 1,
201
+ },
202
+ form: {
203
+ justifyContent: 'flex-start',
204
+ },
205
+ }}
206
+ PaperProps={{
207
+ style: {
208
+ minWidth: isMobile ? '100%' : '500px',
209
+ },
210
+ }}>
211
+ <Elements options={{ clientSecret, locale: locale === 'zh' ? 'zh-CN' : 'en' }} stripe={stripePromise}>
197
212
  <StripeCheckoutForm
198
213
  clientSecret={clientSecret}
199
214
  intentType={intentType}
@@ -577,7 +577,6 @@ export const Root: React.FC<RootProps> = styled(Box)<RootProps>`
577
577
  .MuiButtonBase-root {
578
578
  font-size: 1.3rem;
579
579
  position: relative;
580
- padding: 4px 22px;
581
580
  }
582
581
 
583
582
  .cko-submit-progress {
@@ -41,13 +41,13 @@ export default function ProductCard({ size, variant, name, logo, description, ex
41
41
  <Typography
42
42
  variant="body1"
43
43
  title={description}
44
- sx={{ fontSize: '0.85rem', mb: 0.5, lineHeight: 1.2, textAlign: 'left' }}
44
+ sx={{ fontSize: '0.74375rem', mb: 0.5, lineHeight: 1.2, textAlign: 'left' }}
45
45
  color="text.lighter">
46
46
  {description}
47
47
  </Typography>
48
48
  )}
49
49
  {extra && (
50
- <Box sx={{ fontSize: '0.85rem' }} color="text.lighter">
50
+ <Box sx={{ fontSize: '0.74375rem' }} color="text.lighter">
51
51
  {extra}
52
52
  </Box>
53
53
  )}
@@ -86,7 +86,7 @@ export default function ProductItem({
86
86
  {primaryText}
87
87
  </Typography>
88
88
  {pricing.secondary && (
89
- <Typography sx={{ fontSize: '0.85rem', color: 'text.lighter' }}>{pricing.secondary}</Typography>
89
+ <Typography sx={{ fontSize: '0.74375rem', color: 'text.lighter' }}>{pricing.secondary}</Typography>
90
90
  )}
91
91
  </Stack>
92
92
  </Stack>
@@ -22,7 +22,7 @@ export default function ProductSkeleton({ count }: { count: number }) {
22
22
  <Typography component="div" variant="h4" sx={{ width: '50%' }}>
23
23
  <Skeleton />
24
24
  </Typography>
25
- <Skeleton variant="text" sx={{ fontSize: '1rem', width: '60%' }} />
25
+ <Skeleton variant="text" sx={{ fontSize: '0.875rem', width: '60%' }} />
26
26
  <Typography component="div" variant="h3" sx={{ width: '60%' }}>
27
27
  <Skeleton />
28
28
  </Typography>
@@ -31,7 +31,7 @@ export default function ProductSkeleton({ count }: { count: number }) {
31
31
  </Typography>
32
32
  {Array.from({ length: count }).map((_, i) => (
33
33
  // eslint-disable-next-line react/no-array-index-key
34
- <Skeleton key={i} variant="text" sx={{ fontSize: '1rem', width: '60%' }} />
34
+ <Skeleton key={i} variant="text" sx={{ fontSize: '0.875rem', width: '60%' }} />
35
35
  ))}
36
36
  </Stack>
37
37
  </Fade>
@@ -4,7 +4,7 @@ export default function DonationSkeleton() {
4
4
  return (
5
5
  <Fade in>
6
6
  <Stack direction="column">
7
- <Skeleton variant="text" sx={{ fontSize: '2rem', width: '40%' }} />
7
+ <Skeleton variant="text" sx={{ fontSize: '1.75rem', width: '40%' }} />
8
8
  <Skeleton sx={{ mt: 2 }} variant="rounded" height={40} />
9
9
  <Divider
10
10
  sx={{
@@ -5,7 +5,7 @@ export default function OverviewSkeleton() {
5
5
  <Fade in>
6
6
  <Stack direction="column">
7
7
  <Stack direction="row" alignItems="center" spacing={2}>
8
- <Skeleton variant="text" sx={{ fontSize: '2rem', width: '40%' }} />
8
+ <Skeleton variant="text" sx={{ fontSize: '1.75rem', width: '40%' }} />
9
9
  </Stack>
10
10
  <Skeleton sx={{ mt: 2 }} variant="rounded" height={100} />
11
11
  <Typography mt={2} component="div" variant="h4">
@@ -4,7 +4,7 @@ export default function PaymentSkeleton() {
4
4
  return (
5
5
  <Fade in>
6
6
  <Stack direction="column">
7
- <Skeleton variant="text" sx={{ fontSize: '2rem', width: '40%' }} />
7
+ <Skeleton variant="text" sx={{ fontSize: '1.75rem', width: '40%' }} />
8
8
  <Skeleton sx={{ mt: 2 }} variant="rounded" height={68} />
9
9
  <Box mt={1}>
10
10
  <Typography component="div" variant="h4" mb={-1}>
@@ -1,7 +1,6 @@
1
1
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
2
2
  import type { DonationSettings, TLineItemExpanded, TPaymentCurrency } from '@blocklet/payment-types';
3
3
  import { HelpOutline } from '@mui/icons-material';
4
- import { LoadingButton } from '@mui/lab';
5
4
  import { Box, Divider, Fade, Grow, Stack, Tooltip, Typography, Collapse, IconButton } from '@mui/material';
6
5
  import type { IconButtonProps } from '@mui/material';
7
6
  import { BN, fromTokenToUnit, fromUnitToToken } from '@ocap/util';
@@ -19,6 +18,7 @@ import ProductItem from './product-item';
19
18
  import Livemode from '../components/livemode';
20
19
  import { usePaymentContext } from '../contexts/payment';
21
20
  import { useMobile } from '../hooks/mobile';
21
+ import LoadingButton from '../components/loading-button';
22
22
 
23
23
  // const shake = keyframes`
24
24
  // 0% {
@@ -366,7 +366,7 @@ export default function PaymentSummary({
366
366
  {headlines.then && headlines.showThen && (
367
367
  <Typography
368
368
  component="div"
369
- sx={{ fontSize: '0.9rem', color: 'text.lighter', textAlign: 'right', margin: '-2px 0 8px' }}>
369
+ sx={{ fontSize: '0.7875rem', color: 'text.lighter', textAlign: 'right', margin: '-2px 0 8px' }}>
370
370
  {headlines.then}
371
371
  </Typography>
372
372
  )}
@@ -60,9 +60,10 @@ export function PaymentThemeProvider({
60
60
  },
61
61
  styleOverrides: {
62
62
  root: {
63
- fontSize: '1rem',
63
+ fontSize: '0.875rem',
64
64
  fontWeight: 500,
65
65
  textTransform: 'none',
66
+ boxShadow: 'none',
66
67
  },
67
68
  containedPrimary: {
68
69
  backgroundColor: 'var(--buttons-button-inverted, #010714)',
@@ -108,6 +109,7 @@ export function PaymentThemeProvider({
108
109
  styleOverrides: {
109
110
  root: {
110
111
  textTransform: 'none',
112
+ fontSize: '0.875rem',
111
113
  },
112
114
  },
113
115
  },
@@ -2,7 +2,7 @@ import type { TypographyOptions } from '@mui/material/styles/createTypography';
2
2
 
3
3
  export const typography: TypographyOptions = {
4
4
  h1: {
5
- fontSize: '1.875rem',
5
+ fontSize: '1.5rem',
6
6
  lineHeight: 1.2,
7
7
  fontWeight: 800,
8
8
  letterSpacing: '-.025em',
@@ -14,38 +14,38 @@ export const typography: TypographyOptions = {
14
14
  letterSpacing: '-.025em',
15
15
  },
16
16
  h3: {
17
- fontSize: '1.25rem',
17
+ fontSize: '1.09375rem',
18
18
  lineHeight: 1.4,
19
19
  fontWeight: 600,
20
20
  letterSpacing: '-.025em',
21
21
  },
22
22
  h4: {
23
- fontSize: '1.125rem',
23
+ fontSize: '1.09375rem',
24
24
  lineHeight: 1.5,
25
25
  fontWeight: 600,
26
26
  },
27
27
  h5: {
28
- fontSize: '1rem',
28
+ fontSize: '0.875rem',
29
29
  lineHeight: 1.75,
30
30
  fontWeight: 400,
31
31
  },
32
32
  h6: {
33
- fontSize: '1rem',
33
+ fontSize: '0.875rem',
34
34
  lineHeight: 1.75,
35
35
  fontWeight: 400,
36
36
  },
37
37
  subtitle1: {
38
- fontSize: '1rem',
38
+ fontSize: '0.875rem',
39
39
  lineHeight: 1.75,
40
40
  fontWeight: 400,
41
41
  },
42
42
  subtitle2: {
43
- fontSize: '1rem',
43
+ fontSize: '0.875rem',
44
44
  lineHeight: 1.75,
45
45
  fontWeight: 400,
46
46
  },
47
47
  body1: {
48
- fontSize: '1rem',
48
+ fontSize: '0.875rem',
49
49
  lineHeight: 1.75,
50
50
  },
51
51