payment-kit 1.13.46 → 1.13.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/api/dev.ts CHANGED
@@ -3,4 +3,4 @@ import { setupClient } from 'vite-plugin-blocklet';
3
3
 
4
4
  import { app } from './src';
5
5
 
6
- setupClient(app);
6
+ setupClient(app, { port: 47069 });
package/blocklet.yml CHANGED
@@ -14,7 +14,7 @@ repository:
14
14
  type: git
15
15
  url: git+https://github.com/blocklet/payment-kit.git
16
16
  specVersion: 1.2.8
17
- version: 1.13.46
17
+ version: 1.13.47
18
18
  logo: logo.png
19
19
  files:
20
20
  - dist
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payment-kit",
3
- "version": "1.13.46",
3
+ "version": "1.13.47",
4
4
  "scripts": {
5
5
  "dev": "blocklet dev",
6
6
  "eject": "vite eject",
@@ -40,25 +40,25 @@
40
40
  ]
41
41
  },
42
42
  "dependencies": {
43
- "@arcblock/did": "^1.18.93",
43
+ "@arcblock/did": "^1.18.95",
44
44
  "@arcblock/did-auth-storage-nedb": "^1.7.1",
45
- "@arcblock/did-connect": "^2.8.6",
46
- "@arcblock/did-util": "^1.18.93",
47
- "@arcblock/ux": "^2.8.6",
45
+ "@arcblock/did-connect": "^2.8.7",
46
+ "@arcblock/did-util": "^1.18.95",
47
+ "@arcblock/ux": "^2.8.7",
48
48
  "@blocklet/logger": "1.16.17",
49
49
  "@blocklet/sdk": "1.16.17",
50
- "@blocklet/ui-react": "^2.8.6",
50
+ "@blocklet/ui-react": "^2.8.7",
51
51
  "@blocklet/uploader": "^0.0.33",
52
- "@mui/icons-material": "^5.14.15",
53
- "@mui/lab": "^5.0.0-alpha.150",
54
- "@mui/material": "^5.14.15",
55
- "@mui/styles": "^5.14.15",
56
- "@mui/system": "^5.14.15",
57
- "@ocap/asset": "^1.18.93",
58
- "@ocap/client": "^1.18.93",
59
- "@ocap/mcrypto": "^1.18.93",
60
- "@ocap/util": "^1.18.93",
61
- "@ocap/wallet": "^1.18.93",
52
+ "@mui/icons-material": "^5.14.16",
53
+ "@mui/lab": "^5.0.0-alpha.151",
54
+ "@mui/material": "^5.14.16",
55
+ "@mui/styles": "^5.14.16",
56
+ "@mui/system": "^5.14.16",
57
+ "@ocap/asset": "^1.18.95",
58
+ "@ocap/client": "^1.18.95",
59
+ "@ocap/mcrypto": "^1.18.95",
60
+ "@ocap/util": "^1.18.95",
61
+ "@ocap/wallet": "^1.18.95",
62
62
  "@stripe/react-stripe-js": "^2.3.1",
63
63
  "@stripe/stripe-js": "^2.1.10",
64
64
  "ahooks": "^3.7.8",
@@ -88,7 +88,7 @@
88
88
  "react-error-boundary": "^4.0.11",
89
89
  "react-hook-form": "^7.47.0",
90
90
  "react-international-phone": "^3.1.2",
91
- "react-router-dom": "^6.17.0",
91
+ "react-router-dom": "^6.18.0",
92
92
  "rimraf": "^3.0.2",
93
93
  "sequelize": "^6.33.0",
94
94
  "sqlite3": "^5.1.6",
@@ -103,12 +103,12 @@
103
103
  "@abtnode/types": "1.16.17",
104
104
  "@arcblock/eslint-config": "^0.2.4",
105
105
  "@arcblock/eslint-config-ts": "^0.2.4",
106
- "@did-pay/types": "1.13.46",
106
+ "@did-pay/types": "1.13.47",
107
107
  "@types/cookie-parser": "^1.4.5",
108
108
  "@types/cors": "^2.8.15",
109
109
  "@types/dotenv-flow": "^3.3.2",
110
110
  "@types/express": "^4.17.20",
111
- "@types/node": "^18.18.7",
111
+ "@types/node": "^18.18.8",
112
112
  "@types/react": "^18.2.33",
113
113
  "@types/react-dom": "^18.2.14",
114
114
  "@vitejs/plugin-react": "^2.2.0",
@@ -140,5 +140,5 @@
140
140
  "parser": "typescript"
141
141
  }
142
142
  },
143
- "gitHead": "7c37d3e6f4814056ddc98033b257707fbefba2d9"
143
+ "gitHead": "e917c1f665d97114b37ddb566329a1f9c6a9ba6b"
144
144
  }
@@ -1,13 +1,12 @@
1
1
  import 'react-international-phone/style.css';
2
2
 
3
- import SessionManager from '@arcblock/did-connect/lib/SessionManager';
4
3
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
5
- import LocaleSelector from '@arcblock/ux/lib/Locale/selector';
4
+ import { useTheme } from '@arcblock/ux/lib/Theme';
6
5
  import Toast from '@arcblock/ux/lib/Toast';
7
6
  import type { TCheckoutSessionExpanded, TCustomer, TPaymentIntent, TPaymentMethodExpanded } from '@did-pay/types';
8
7
  import { LoadingButton } from '@mui/lab';
9
- import { Avatar, Fade, InputAdornment, MenuItem, Select, Stack, Tooltip, Typography } from '@mui/material';
10
- import { useSetState } from 'ahooks';
8
+ import { Avatar, Fade, InputAdornment, MenuItem, Select, Stack, Typography } from '@mui/material';
9
+ import { useCreation, useSetState, useSize } from 'ahooks';
11
10
  import { PhoneNumberUtil } from 'google-libphonenumber';
12
11
  import pWaitFor from 'p-wait-for';
13
12
  import { useEffect } from 'react';
@@ -21,6 +20,7 @@ import FormInput from '../../input';
21
20
  import AddressForm from './address';
22
21
  import PhoneInput from './phone';
23
22
  import StripeCheckout from './stripe';
23
+ import UserButtons from './user-buttons';
24
24
 
25
25
  const phoneUtil = PhoneNumberUtil.getInstance();
26
26
 
@@ -72,6 +72,7 @@ export default function PaymentForm({
72
72
  onPaid,
73
73
  onError,
74
74
  }: PageData) {
75
+ const theme = useTheme();
75
76
  const { t } = useLocaleContext();
76
77
  const { session, connectApi } = useSessionContext();
77
78
  const { control, getValues, setValue, handleSubmit } = useFormContext();
@@ -112,6 +113,17 @@ export default function PaymentForm({
112
113
  const paymentCurrency = useWatch({ control, name: 'payment_currency' });
113
114
  const paymentCurrencies = paymentMethods.find((x) => x.id === paymentMethod)?.payment_currencies || [];
114
115
 
116
+ const domSize = useSize(document.body);
117
+
118
+ const isCloumnLayout = useCreation(() => {
119
+ if (domSize) {
120
+ if (domSize?.width <= theme.breakpoints.values.md) {
121
+ return true;
122
+ }
123
+ }
124
+ return false;
125
+ }, [domSize, theme]);
126
+
115
127
  const payee = getStatementDescriptor(checkoutSession.line_items);
116
128
  const buttonText = session.user
117
129
  ? t(`checkout.${checkoutSession.mode}`)
@@ -249,16 +261,7 @@ export default function PaymentForm({
249
261
  <Stack className="cko-payment-contact">
250
262
  <Stack direction="row" sx={{ mb: 1 }} alignItems="center" justifyContent="space-between">
251
263
  <Typography sx={{ color: 'text.primary', fontWeight: 600 }}>{t('checkout.contact')}</Typography>
252
- <Stack direction="row" alignItems="center" justifyContent="space-between">
253
- <LocaleSelector showText={false} />
254
- {session.user ? (
255
- <SessionManager session={session} />
256
- ) : (
257
- <Tooltip title={t('checkout.login')} arrow>
258
- <SessionManager session={session} />
259
- </Tooltip>
260
- )}
261
- </Stack>
264
+ {isCloumnLayout ? null : <UserButtons />}
262
265
  </Stack>
263
266
  <Stack direction="column" className="cko-payment-form" spacing={0}>
264
267
  <FormInput
@@ -0,0 +1,24 @@
1
+ import SessionManager from '@arcblock/did-connect/lib/SessionManager';
2
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
3
+ import LocaleSelector from '@arcblock/ux/lib/Locale/selector';
4
+ import { Stack, Tooltip } from '@mui/material';
5
+
6
+ import { useSessionContext } from '../../../contexts/session';
7
+
8
+ export default function UserButtons() {
9
+ const { t } = useLocaleContext();
10
+ const { session } = useSessionContext();
11
+
12
+ return (
13
+ <Stack direction="row" alignItems="center" justifyContent="space-between">
14
+ <LocaleSelector showText={false} />
15
+ {session.user ? (
16
+ <SessionManager session={session} />
17
+ ) : (
18
+ <Tooltip title={t('checkout.login')} arrow>
19
+ <SessionManager session={session} />
20
+ </Tooltip>
21
+ )}
22
+ </Stack>
23
+ );
24
+ }
@@ -1,9 +1,11 @@
1
+ import { useTheme } from '@arcblock/ux/lib/Theme';
1
2
  import type { TCheckoutSessionExpanded } from '@did-pay/types';
2
3
  import { Avatar, Stack, Typography } from '@mui/material';
3
- import { useLocalStorageState } from 'ahooks';
4
+ import { useCreation, useLocalStorageState, useSize } from 'ahooks';
4
5
 
5
6
  import { getStatementDescriptor } from '../../libs/util';
6
7
  import Livemode from '../livemode';
8
+ import UserButtons from './form/user-buttons';
7
9
 
8
10
  type Props = {
9
11
  checkoutSession: TCheckoutSessionExpanded;
@@ -12,12 +14,27 @@ type Props = {
12
14
  export default function PaymentHeader({ checkoutSession }: Props) {
13
15
  const [livemode] = useLocalStorageState('livemode', { defaultValue: true });
14
16
  const brand = getStatementDescriptor(checkoutSession.line_items);
17
+ const theme = useTheme();
18
+
19
+ const domSize = useSize(document.body);
20
+
21
+ const isCloumnLayout = useCreation(() => {
22
+ if (domSize) {
23
+ if (domSize?.width <= theme.breakpoints.values.md) {
24
+ return true;
25
+ }
26
+ }
27
+ return false;
28
+ }, [domSize, theme]);
15
29
 
16
30
  return (
17
- <Stack className="cko-header" direction="row" spacing={1} alignItems="center">
18
- <Avatar variant="square" src={window.blocklet.appLogo} sx={{ width: 32, height: 32 }} />
19
- <Typography sx={{ color: 'text.primary', fontWeight: 600 }}>{brand}</Typography>
20
- {!livemode && <Livemode />}
31
+ <Stack className="cko-header" direction="row" spacing={1} alignItems="center" justifyContent="space-between">
32
+ <Stack direction="row" spacing={1} alignItems="center">
33
+ <Avatar variant="square" src={window.blocklet.appLogo} sx={{ width: 32, height: 32 }} />
34
+ <Typography sx={{ color: 'text.primary', fontWeight: 600 }}>{brand}</Typography>
35
+ {!livemode && <Livemode />}
36
+ </Stack>
37
+ {isCloumnLayout ? <UserButtons /> : null}
21
38
  </Stack>
22
39
  );
23
40
  }
@@ -81,7 +81,7 @@ export default function CheckoutPay({
81
81
  if (!checkoutSession) {
82
82
  return (
83
83
  <PaymentRoot>
84
- <Stack direction="row" className="cko-container">
84
+ <Stack className="cko-container">
85
85
  <Stack className="cko-overview">
86
86
  <OverviewSkeleton />
87
87
  </Stack>
@@ -223,7 +223,7 @@ export function CheckoutPayMain({
223
223
  return (
224
224
  <FormProvider {...methods}>
225
225
  <PaymentRoot>
226
- <Stack direction="row" className="cko-container">
226
+ <Stack className="cko-container">
227
227
  <Fade in>
228
228
  <Stack className="cko-overview" direction="column">
229
229
  <PaymentHeader checkoutSession={state.checkoutSession} />
@@ -269,14 +269,16 @@ export function CheckoutPayMain({
269
269
  export const PaymentRoot = styled(Box)`
270
270
  box-sizing: border-box;
271
271
  display: flex;
272
- flex-wrap: nowrap;
272
+ flex-direction: column;
273
273
  justify-content: center;
274
- min-height: 0;
274
+ align-items: center;
275
+ min-height: 100vh;
276
+ position: relative;
275
277
 
276
278
  &:before {
277
279
  animation-fill-mode: both;
278
280
  background: #ffffff;
279
- content: ' ';
281
+ content: '';
280
282
  height: 100%;
281
283
  position: fixed;
282
284
  right: 0;
@@ -288,21 +290,30 @@ export const PaymentRoot = styled(Box)`
288
290
 
289
291
  .cko-container {
290
292
  width: 100%;
291
- max-width: 920px;
293
+ max-width: 1000px;
292
294
  display: flex;
293
- align-items: flex-start;
295
+ flex-direction: row;
294
296
  justify-content: space-between;
295
297
  position: relative;
296
- transform: translateY(max(48px, calc(50vh - 55%)));
298
+ padding: 0 16px;
297
299
  }
298
300
 
299
301
  .cko-overview {
300
- width: 380px;
302
+ width: 400px;
301
303
  min-height: 540px;
304
+ position: relative;
305
+ }
306
+ .cko-header {
307
+ left: 0;
308
+ margin-bottom: 0;
309
+ position: absolute;
310
+ right: 0;
311
+ top: 0;
312
+ transition: background-color 0.15s ease, box-shadow 0.15s ease-out;
302
313
  }
303
314
 
304
315
  .cko-payment {
305
- width: 380px;
316
+ width: 400px;
306
317
  .MuiInputBase-root {
307
318
  border-radius: 0;
308
319
  }
@@ -337,10 +348,38 @@ export const PaymentRoot = styled(Box)`
337
348
  }
338
349
  }
339
350
 
351
+ .cko-header {
352
+ }
353
+
340
354
  .cko-footer {
341
355
  position: absolute;
342
356
  bottom: 0;
343
- left: 0;
357
+ left: 12px;
344
358
  margin: 12px 0;
345
359
  }
360
+
361
+ @media (max-width: ${({ theme }) => theme.breakpoints.values.md}px) {
362
+ &:before {
363
+ display: none;
364
+ }
365
+ .cko-container {
366
+ flex-direction: column;
367
+ align-items: center;
368
+ gap: 24px;
369
+ min-width: 350px;
370
+ max-width: 400px;
371
+ }
372
+ .cko-overview {
373
+ width: 100%;
374
+ min-height: auto;
375
+ }
376
+ .cko-payment {
377
+ width: 100%;
378
+ }
379
+
380
+ .cko-footer {
381
+ position: static;
382
+ margin-top: 0;
383
+ }
384
+ }
346
385
  `;
@@ -82,7 +82,12 @@ export default function PaymentSummary({
82
82
 
83
83
  return (
84
84
  <Fade in>
85
- <Stack className="cko-product" direction="column" sx={{ mt: 4 }}>
85
+ <Stack
86
+ className="cko-product"
87
+ direction="column"
88
+ sx={{
89
+ mt: 8,
90
+ }}>
86
91
  <Stack className="cko-product-summary" sx={{ mb: 4 }}>
87
92
  <Typography sx={{ fontWeight: 500, fontSize: '1.15rem', color: 'text.secondary' }}>
88
93
  {headlines.action}
@@ -120,7 +125,15 @@ export default function PaymentSummary({
120
125
  direction="column"
121
126
  alignItems="flex-end"
122
127
  spacing={0.5}
123
- sx={{ border: '1px solid #eee', borderRadius: 1, padding: 1, mt: 8, mb: 4 }}>
128
+ sx={{
129
+ border: '1px solid #eee',
130
+ borderRadius: 1,
131
+ padding: 1,
132
+ mt: {
133
+ xs: 4,
134
+ md: 8,
135
+ },
136
+ }}>
124
137
  <ProductItem
125
138
  item={{ quantity: 1, price: data, price_id: data.id, cross_sell: true } as TLineItemExpanded}
126
139
  session={checkoutSession}
@@ -10,7 +10,7 @@ export default function Livemode() {
10
10
  sx={{
11
11
  ml: 2,
12
12
  height: 18,
13
- lineHeight: 18,
13
+ lineHeight: 1,
14
14
  textTransform: 'uppercase',
15
15
  fontSize: '0.8rem',
16
16
  fontWeight: 'bold',
@@ -4,7 +4,6 @@ import type { Paginated, TInvoiceExpanded } from '@did-pay/types';
4
4
  import { Box, Button, CircularProgress, Stack, Typography } from '@mui/material';
5
5
  import { fromUnitToToken } from '@ocap/util';
6
6
  import { useInfiniteScroll } from 'ahooks';
7
- import React from 'react';
8
7
  import { Link } from 'react-router-dom';
9
8
 
10
9
  import api from '../../../libs/api';
@@ -63,12 +62,23 @@ export default function CustomerInvoiceList({ customer_id }: Props) {
63
62
  const grouped = groupByDate(data.list);
64
63
 
65
64
  return (
66
- <Stack direction="column" spacing={3} sx={{ mt: 1 }}>
65
+ <Stack direction="column" gap={3} sx={{ mt: 1 }}>
67
66
  {Object.entries(grouped).map(([date, invoices]) => (
68
- <React.Fragment key={date}>
69
- <Typography sx={{ fontWeight: 'bold', color: 'text.secondary', mt: 2 }}>{date}</Typography>
67
+ <Box key={date}>
68
+ <Typography sx={{ fontWeight: 'bold', color: 'text.secondary', mt: 2, mb: 1 }}>{date}</Typography>
70
69
  {invoices.map((invoice) => (
71
- <Stack key={invoice.id} direction="row" justifyContent="space-between" spacing={3} flexWrap="nowrap">
70
+ <Stack
71
+ key={invoice.id}
72
+ direction={{
73
+ xs: 'column',
74
+ sm: 'row',
75
+ }}
76
+ gap={{
77
+ xs: 0.5,
78
+ sm: 1.5,
79
+ md: 4,
80
+ }}
81
+ flexWrap="nowrap">
72
82
  <Box flex={2}>
73
83
  <Link to={`/customer/invoice/${invoice.id}`}>
74
84
  <Typography component="span">{invoice.number}</Typography>
@@ -91,7 +101,7 @@ export default function CustomerInvoiceList({ customer_id }: Props) {
91
101
  </Box>
92
102
  </Stack>
93
103
  ))}
94
- </React.Fragment>
104
+ </Box>
95
105
  ))}
96
106
  <Box>
97
107
  {hasMore && (
@@ -99,7 +99,15 @@ export function CurrentSubscriptionsInner({ id, onChange }: Props) {
99
99
  return (
100
100
  <Stack direction="column" spacing={4} sx={{ mt: 2 }}>
101
101
  {data.list.map((subscription) => (
102
- <Stack key={subscription.id} direction="row" justifyContent="space-between" spacing={3}>
102
+ <Stack
103
+ key={subscription.id}
104
+ direction="row"
105
+ justifyContent="space-between"
106
+ gap={{
107
+ xs: 1,
108
+ sm: 3,
109
+ }}
110
+ flexWrap="wrap">
103
111
  <Stack direction="column" spacing={0.5}>
104
112
  <Stack direction="row" spacing={1} alignItems="center">
105
113
  <AvatarGroup max={3}>
@@ -14,6 +14,8 @@ export default function SectionHeader(props: Props) {
14
14
  direction="row"
15
15
  justifyContent="space-between"
16
16
  alignItems="center"
17
+ flexWrap="wrap"
18
+ gap={1}
17
19
  sx={{ mb: props.mb, pb: 1, width: 1, borderBottom: '1px solid #eee' }}>
18
20
  <Typography variant="h6" sx={{ fontWeight: 600 }}>
19
21
  {props.title}
@@ -6,7 +6,7 @@ export default function Status(props: ChipProps) {
6
6
  size="small"
7
7
  variant="outlined"
8
8
  {...props}
9
- sx={{ ...(props.sx || {}), borderRadius: '4px', height: 20, lineHeight: 20, textTransform: 'capitalize' }}
9
+ sx={{ ...(props.sx || {}), borderRadius: '4px', height: 20, lineHeight: 1, textTransform: 'capitalize' }}
10
10
  />
11
11
  );
12
12
  }
@@ -77,18 +77,32 @@ export default function PricingTable({ id }: Props) {
77
77
 
78
78
  if (error) {
79
79
  return (
80
- <div style={{ height: '90vh', width: '100vw' }}>
80
+ <Box
81
+ sx={{
82
+ width: '100vw',
83
+ minHeight: '90vh',
84
+ pb: 4,
85
+ display: 'flex',
86
+ flexDirection: 'column',
87
+ }}>
81
88
  <Header />
82
89
  <Center relative="parent">
83
90
  <Alert severity="error">{error.message}</Alert>
84
91
  </Center>
85
- </div>
92
+ </Box>
86
93
  );
87
94
  }
88
95
 
89
96
  if (loading || !data) {
90
97
  return (
91
- <div style={{ height: '90vh', width: '100vw' }}>
98
+ <Box
99
+ sx={{
100
+ width: '100vw',
101
+ minHeight: '90vh',
102
+ pb: 4,
103
+ display: 'flex',
104
+ flexDirection: 'column',
105
+ }}>
92
106
  <Header />
93
107
  <Center>
94
108
  <Stack direction="column" alignItems="center" spacing={4}>
@@ -98,25 +112,32 @@ export default function PricingTable({ id }: Props) {
98
112
  <Typography component="div" variant="h6" sx={{ width: '10%' }}>
99
113
  <Skeleton />
100
114
  </Typography>
101
- <Stack direction="row" flexWrap="wrap" spacing={5}>
115
+ <Stack flexWrap="wrap" direction="row" gap={{ xs: 3, sm: 5, md: 10 }} justifyContent="center">
102
116
  <ProductSkeleton key={1} count={2} />
103
117
  <ProductSkeleton key={2} count={3} />
104
118
  <ProductSkeleton key={3} count={4} />
105
119
  </Stack>
106
120
  </Stack>
107
121
  </Center>
108
- </div>
122
+ </Box>
109
123
  );
110
124
  }
111
125
 
112
126
  if (data.items.length === 0) {
113
127
  return (
114
- <div style={{ height: '90vh', width: '100vw' }}>
128
+ <Box
129
+ sx={{
130
+ width: '100vw',
131
+ minHeight: '90vh',
132
+ pb: 4,
133
+ display: 'flex',
134
+ flexDirection: 'column',
135
+ }}>
115
136
  <Header />
116
137
  <Center relative="parent">
117
138
  <Alert severity="warning">{t('checkout.noPricing')}</Alert>
118
139
  </Center>
119
- </div>
140
+ </Box>
120
141
  );
121
142
  }
122
143
 
@@ -137,16 +158,45 @@ export default function PricingTable({ id }: Props) {
137
158
  };
138
159
 
139
160
  return (
140
- <div style={{ height: '90vh', width: '100vw' }}>
161
+ <Box
162
+ sx={{
163
+ width: '100vw',
164
+ minHeight: '90vh',
165
+ pb: 4,
166
+ display: {
167
+ xs: 'block',
168
+ sm: 'flex',
169
+ },
170
+ flexDirection: 'column',
171
+ }}>
141
172
  <Header />
142
173
  <Center relative="parent">
143
- <Stack direction="column" alignItems="center" spacing={5}>
174
+ <Stack
175
+ direction="column"
176
+ alignItems="center"
177
+ sx={{
178
+ pt: {
179
+ xs: 4,
180
+ sm: 2,
181
+ },
182
+ gap: {
183
+ xs: 3,
184
+ sm: 5,
185
+ },
186
+ }}>
144
187
  <Typography variant="h4" color="text.primary" fontWeight={600}>
145
188
  {data.name}
146
189
  {!livemode && <Livemode />}
147
190
  </Typography>
148
191
  {Object.keys(recurring).length > 1 && (
149
- <ToggleButtonGroup value={state.interval} onChange={(_, value) => setState({ interval: value })} exclusive>
192
+ <ToggleButtonGroup
193
+ value={state.interval}
194
+ onChange={(_, value) => {
195
+ if (value !== null) {
196
+ setState({ interval: value });
197
+ }
198
+ }}
199
+ exclusive>
150
200
  {Object.keys(recurring).map((x) => (
151
201
  <ToggleButton key={x} value={x} sx={{ textTransform: 'capitalize' }}>
152
202
  {formatRecurring(recurring[x] as PriceRecurring, true, '', locale)}
@@ -154,7 +204,7 @@ export default function PricingTable({ id }: Props) {
154
204
  ))}
155
205
  </ToggleButtonGroup>
156
206
  )}
157
- <Stack direction="row" flexWrap="wrap" spacing={5}>
207
+ <Stack flexWrap="wrap" direction="row" gap={{ xs: 3, sm: 5, md: 10 }} justifyContent="center">
158
208
  {grouped[state.interval]?.map((x) => {
159
209
  return (
160
210
  <Fade in>
@@ -226,6 +276,6 @@ export default function PricingTable({ id }: Props) {
226
276
  </Stack>
227
277
  </Stack>
228
278
  </Center>
229
- </div>
279
+ </Box>
230
280
  );
231
281
  }