@blocklet/payment-react 1.13.260 → 1.13.262

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.
@@ -56,11 +56,34 @@ export default function CheckoutTable({ id, mode, onPaid, onError, onChange, ext
56
56
  }
57
57
  if (!sessionId && !hashSessionId) {
58
58
  if (mode === "standalone") {
59
- return /* @__PURE__ */ jsxs(Stack, { direction: "column", alignItems: "center", spacing: 4, children: [
60
- /* @__PURE__ */ jsxs(Typography, { variant: "h4", color: "text.primary", fontWeight: 600, children: [
61
- data.name,
62
- !data.livemode && /* @__PURE__ */ jsx(Livemode, {})
63
- ] }),
59
+ return /* @__PURE__ */ jsxs(Stack, { direction: "column", alignItems: "center", children: [
60
+ /* @__PURE__ */ jsxs(
61
+ Box,
62
+ {
63
+ sx: {
64
+ display: "flex",
65
+ flexDirection: "column",
66
+ fontSize: "24px",
67
+ margin: "20px 90px !important",
68
+ textAlign: "center"
69
+ },
70
+ children: [
71
+ !data.livemode && /* @__PURE__ */ jsx(Livemode, { sx: { display: "flex", marginBottom: "8px" } }),
72
+ /* @__PURE__ */ jsx(
73
+ Typography,
74
+ {
75
+ color: "text.primary",
76
+ fontWeight: 600,
77
+ sx: {
78
+ lineHeight: "32px",
79
+ fontSize: "24px"
80
+ },
81
+ children: data.name
82
+ }
83
+ )
84
+ ]
85
+ }
86
+ ),
64
87
  /* @__PURE__ */ jsx(PricingTable, { table: data, onSelect: handleSelect })
65
88
  ] });
66
89
  }
@@ -1,9 +1,10 @@
1
1
  /// <reference types="react" />
2
+ import { ChipOwnProps } from '@mui/material';
2
3
  type Props = {
3
4
  color?: string;
4
5
  backgroundColor?: string;
5
- };
6
- declare function Livemode({ color, backgroundColor }: Props): import("react").JSX.Element;
6
+ } & ChipOwnProps;
7
+ declare function Livemode({ color, backgroundColor, sx }: Props): import("react").JSX.Element;
7
8
  declare namespace Livemode {
8
9
  var defaultProps: {
9
10
  color: string;
@@ -1,7 +1,7 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
3
3
  import { Chip } from "@mui/material";
4
- export default function Livemode({ color, backgroundColor }) {
4
+ export default function Livemode({ color, backgroundColor, sx }) {
5
5
  const { t } = useLocaleContext();
6
6
  return /* @__PURE__ */ jsx(
7
7
  Chip,
@@ -17,7 +17,8 @@ export default function Livemode({ color, backgroundColor }) {
17
17
  fontWeight: "bold",
18
18
  borderRadius: "4px",
19
19
  backgroundColor,
20
- color
20
+ color,
21
+ ...sx
21
22
  }
22
23
  }
23
24
  );
@@ -60,13 +60,13 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
60
60
  }
61
61
  @media (min-width: ${({ theme }) => theme.breakpoints.values.md}px) {
62
62
  .price-table-wrap:has(> div:nth-child(1)) {
63
- width: 320px !important;
63
+ max-width: 360px !important;
64
64
  }
65
65
  .price-table-wrap:has(> div:nth-child(2)) {
66
- width: 720px !important;
66
+ max-width: 720px !important;
67
67
  }
68
68
  .price-table-wrap:has(> div:nth-child(3)) {
69
- width: 960px !important;
69
+ max-width: 1080px !important;
70
70
  }
71
71
  .price-table-wrap:has(> div:nth-child(1)) > .price-table-item {
72
72
  width: 90% !important;
@@ -85,10 +85,6 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
85
85
  direction: "column",
86
86
  alignItems: alignItems === "center" ? "center" : "flex-start",
87
87
  sx: {
88
- pt: {
89
- xs: 4,
90
- sm: 2
91
- },
92
88
  gap: {
93
89
  xs: 3,
94
90
  sm: mode === "select" ? 3 : 5
@@ -98,16 +94,42 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
98
94
  Object.keys(recurring).length > 1 && /* @__PURE__ */ jsx(
99
95
  ToggleButtonGroup,
100
96
  {
101
- color: "primary",
102
97
  size: "small",
103
98
  value: state.interval,
99
+ sx: {
100
+ padding: "4px",
101
+ borderRadius: "36px",
102
+ height: "40px",
103
+ boxSizing: "border-box",
104
+ backgroundColor: "#f1f3f5",
105
+ border: 0
106
+ },
104
107
  onChange: (_, value) => {
105
108
  if (value !== null) {
106
109
  setState({ interval: value });
107
110
  }
108
111
  },
109
112
  exclusive: true,
110
- children: Object.keys(recurring).map((x) => /* @__PURE__ */ jsx(ToggleButton, { size: "small", value: x, sx: { textTransform: "capitalize" }, children: formatRecurring(recurring[x], true, "", locale) }, x))
113
+ children: Object.keys(recurring).map((x) => /* @__PURE__ */ jsx(
114
+ ToggleButton,
115
+ {
116
+ size: "small",
117
+ value: x,
118
+ sx: {
119
+ textTransform: "capitalize",
120
+ padding: "5px 12px",
121
+ fontSize: "13px",
122
+ backgroundColor: x === state.interval ? "#fff !important" : "#f1f3f5 !important",
123
+ border: "0px",
124
+ "&.Mui-selected": {
125
+ borderRadius: "9999px !important",
126
+ border: "1px solid #e5e7eb"
127
+ }
128
+ },
129
+ children: formatRecurring(recurring[x], true, "", locale)
130
+ },
131
+ x
132
+ ))
111
133
  }
112
134
  ),
113
135
  /* @__PURE__ */ jsx(
@@ -115,7 +137,7 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
115
137
  {
116
138
  flexWrap: "wrap",
117
139
  direction: "row",
118
- gap: "calc(10px + 3%)",
140
+ gap: "20px",
119
141
  justifyContent: alignItems === "center" ? "center" : "flex-start",
120
142
  className: "price-table-wrap",
121
143
  children: grouped[state.interval]?.map(
@@ -130,7 +152,7 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
130
152
  padding: 4,
131
153
  spacing: 2,
132
154
  direction: "column",
133
- alignItems: "center",
155
+ alignItems: "flex-start",
134
156
  className: "price-table-item",
135
157
  justifyContent: "flex-start",
136
158
  sx: {
@@ -138,37 +160,119 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
138
160
  borderWidth: "1px",
139
161
  borderStyle: "solid",
140
162
  borderColor: mode === "select" && x.is_selected ? "primary.main" : "#eee",
141
- borderRadius: 1,
163
+ borderRadius: 2,
142
164
  transition: "border-color 0.3s ease 0s, box-shadow 0.3s ease 0s",
143
- boxShadow: "0 4px 8px rgba(0, 0, 0, 20%)",
165
+ boxShadow: "0px 0px 0px 1px rgba(3, 7, 18, 0.08), 0px 1px 2px -1px rgba(3, 7, 18, 0.08), 0px 2px 4px rgba(3, 7, 18, 0.04)",
144
166
  "&:hover": {
145
167
  borderColor: mode === "select" && x.is_selected ? "primary.main" : "#ddd",
146
168
  boxShadow: "0 8px 16px rgba(0, 0, 0, 20%)"
147
- }
169
+ },
170
+ padding: "20px",
171
+ position: "relative"
148
172
  },
149
173
  children: [
150
- /* @__PURE__ */ jsxs(Box, { textAlign: "center", children: [
151
- /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: "center", spacing: 1, children: [
152
- /* @__PURE__ */ jsx(Typography, { variant: "h5", color: "text.primary", fontWeight: 600, children: x.product.name }),
153
- x.is_highlight && /* @__PURE__ */ jsx(Chip, { label: x.highlight_text, color: "default", size: "small" })
154
- ] }),
155
- /* @__PURE__ */ jsx(Typography, { color: "text.secondary", children: x.product.description })
156
- ] }),
157
- /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 1, children: [
158
- /* @__PURE__ */ jsx(Amount, { amount: formatPriceAmount(x.price, table.currency, x.product.unit_label) }),
159
- /* @__PURE__ */ jsxs(Stack, { direction: "column", alignItems: "flex-start", children: [
160
- /* @__PURE__ */ jsx(Typography, { component: "span", color: "text.secondary", fontSize: "0.8rem", children: t("payment.checkout.per") }),
161
- /* @__PURE__ */ jsx(Typography, { component: "span", color: "text.secondary", fontSize: "0.8rem", children: formatRecurring(x.price.recurring, false, "", locale) })
162
- ] })
163
- ] }),
164
- /* @__PURE__ */ jsx(Loading, { x, action, onSelect }),
165
- x.product.features.length > 0 && /* @__PURE__ */ jsxs(Box, { children: [
166
- /* @__PURE__ */ jsx(Typography, { children: t("payment.checkout.include") }),
167
- /* @__PURE__ */ jsx(List, { dense: true, children: x.product.features.map((f) => /* @__PURE__ */ jsxs(ListItem, { disableGutters: true, disablePadding: true, children: [
168
- /* @__PURE__ */ jsx(ListItemIcon, { sx: { minWidth: 25 }, children: /* @__PURE__ */ jsx(CheckOutlined, { color: "success", fontSize: "small" }) }),
169
- /* @__PURE__ */ jsx(ListItemText, { primary: f.name })
170
- ] }, f.name)) })
171
- ] })
174
+ /* @__PURE__ */ jsx(Box, { textAlign: "center", children: /* @__PURE__ */ jsxs(
175
+ Stack,
176
+ {
177
+ direction: "column",
178
+ justifyContent: "center",
179
+ alignItems: "flex-start",
180
+ spacing: 1,
181
+ sx: { gap: "12px" },
182
+ children: [
183
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
184
+ /* @__PURE__ */ jsx(
185
+ Typography,
186
+ {
187
+ color: "text.primary",
188
+ fontWeight: 600,
189
+ sx: {
190
+ color: "#4B5563",
191
+ fontSize: "18px !important",
192
+ fontWeight: "600"
193
+ },
194
+ children: x.product.name
195
+ }
196
+ ),
197
+ x.is_highlight && /* @__PURE__ */ jsx(
198
+ Chip,
199
+ {
200
+ label: x.highlight_text,
201
+ color: "default",
202
+ size: "small",
203
+ sx: {
204
+ position: "absolute",
205
+ top: "20px",
206
+ right: "20px"
207
+ }
208
+ }
209
+ )
210
+ ] }),
211
+ /* @__PURE__ */ jsx(
212
+ Amount,
213
+ {
214
+ amount: formatPriceAmount(x.price, table.currency, x.product.unit_label),
215
+ sx: { my: 0, marginTop: "0px !important", fontSize: "48px", fontWeight: "bold" }
216
+ }
217
+ ),
218
+ /* @__PURE__ */ jsx(
219
+ Typography,
220
+ {
221
+ color: "text.secondary",
222
+ sx: {
223
+ marginTop: "0px !important",
224
+ color: "#4b5563",
225
+ fontWeight: "400",
226
+ fontSize: "16px",
227
+ textAlign: "left"
228
+ },
229
+ children: x.product.description
230
+ }
231
+ )
232
+ ]
233
+ }
234
+ ) }),
235
+ x.product.features.length > 0 && /* @__PURE__ */ jsx(Box, { sx: { width: "100%" }, children: /* @__PURE__ */ jsxs(List, { dense: true, sx: { display: "flex", flexDirection: "column", gap: "16px", padding: "0px" }, children: [
236
+ /* @__PURE__ */ jsx(
237
+ Box,
238
+ {
239
+ sx: {
240
+ width: "100%",
241
+ position: "relative",
242
+ borderTop: "1px solid #e5e7eb",
243
+ boxSizing: "border-box",
244
+ height: "1px"
245
+ }
246
+ }
247
+ ),
248
+ x.product.features.map((f) => /* @__PURE__ */ jsxs(ListItem, { disableGutters: true, disablePadding: true, sx: { fontSize: "16px !important" }, children: [
249
+ /* @__PURE__ */ jsx(ListItemIcon, { sx: { minWidth: 25, color: "#059669", fontSize: "64px" }, children: /* @__PURE__ */ jsx(
250
+ CheckOutlined,
251
+ {
252
+ color: "success",
253
+ fontSize: "small",
254
+ sx: {
255
+ color: "#059669",
256
+ fontSize: "18px"
257
+ }
258
+ }
259
+ ) }),
260
+ /* @__PURE__ */ jsx(
261
+ ListItemText,
262
+ {
263
+ sx: {
264
+ ".MuiListItemText-primary": {
265
+ fontSize: "16px",
266
+ color: "#030712",
267
+ fontWeight: "500"
268
+ }
269
+ },
270
+ primary: f.name
271
+ }
272
+ )
273
+ ] }, f.name))
274
+ ] }) }),
275
+ /* @__PURE__ */ jsx(Subscribe, { x, action, onSelect })
172
276
  ]
173
277
  },
174
278
  x?.price_id
@@ -181,7 +285,7 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
181
285
  }
182
286
  ) });
183
287
  }
184
- function Loading({ x, action, onSelect }) {
288
+ function Subscribe({ x, action, onSelect }) {
185
289
  const [state, setState] = useState({ loading: "", loaded: false });
186
290
  const handleSelect = async (priceId) => {
187
291
  try {
@@ -196,10 +300,10 @@ function Loading({ x, action, onSelect }) {
196
300
  LoadingButton,
197
301
  {
198
302
  fullWidth: true,
199
- size: "large",
200
- variant: x.is_highlight || x.is_selected ? "contained" : "outlined",
303
+ size: "medium",
304
+ variant: "contained",
201
305
  color: x.is_highlight || x.is_selected ? "primary" : "info",
202
- sx: { fontSize: "1.2rem" },
306
+ sx: { fontSize: "16px", padding: "10px 20px", lineHeight: "28px" },
203
307
  loading: state.loading === x.price_id && !state.loaded,
204
308
  disabled: x.is_disabled,
205
309
  onClick: () => handleSelect(x.price_id),
package/es/libs/util.js CHANGED
@@ -64,6 +64,9 @@ export const formatLocale = (locale = "en") => {
64
64
  };
65
65
  export const formatPrettyMsLocale = (locale) => locale === "zh" ? "zh_CN" : "en_US";
66
66
  export const formatError = (err) => {
67
+ if (!err) {
68
+ return "Unknown error";
69
+ }
67
70
  const { details, errors, response } = err;
68
71
  if (Array.isArray(errors)) {
69
72
  return errors.map((x) => x.message).join("\n");
@@ -77,7 +80,7 @@ export const formatError = (err) => {
77
80
  return `Validate failed: ${formatted.join(";")}`;
78
81
  }
79
82
  if (response) {
80
- return response.data.error || `${err.message}: ${JSON.stringify(response.data)}`;
83
+ return response.data?.error || `${err.message}: ${JSON.stringify(response.data)}`;
81
84
  }
82
85
  return err.message;
83
86
  };
@@ -1,8 +1,8 @@
1
1
  /// <reference types="react" />
2
+ import { TypographyProps } from '@mui/material';
2
3
  type Props = {
3
4
  amount: string;
4
- sx?: any;
5
- };
5
+ } & TypographyProps;
6
6
  declare function PaymentAmount({ amount, sx }: Props): import("react").JSX.Element;
7
7
  declare namespace PaymentAmount {
8
8
  var defaultProps: {
@@ -18,5 +18,6 @@ export default function PaymentAmount({ amount, sx }) {
18
18
  );
19
19
  }
20
20
  PaymentAmount.defaultProps = {
21
+ // eslint-disable-next-line react/default-props-match-prop-types
21
22
  sx: {}
22
23
  };
@@ -88,12 +88,28 @@ function CheckoutTable({
88
88
  return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
89
89
  direction: "column",
90
90
  alignItems: "center",
91
- spacing: 4,
92
- children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
93
- variant: "h4",
94
- color: "text.primary",
95
- fontWeight: 600,
96
- children: [data.name, !data.livemode && /* @__PURE__ */(0, _jsxRuntime.jsx)(_livemode.default, {})]
91
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_system.Box, {
92
+ sx: {
93
+ display: "flex",
94
+ flexDirection: "column",
95
+ fontSize: "24px",
96
+ margin: "20px 90px !important",
97
+ textAlign: "center"
98
+ },
99
+ children: [!data.livemode && /* @__PURE__ */(0, _jsxRuntime.jsx)(_livemode.default, {
100
+ sx: {
101
+ display: "flex",
102
+ marginBottom: "8px"
103
+ }
104
+ }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
105
+ color: "text.primary",
106
+ fontWeight: 600,
107
+ sx: {
108
+ lineHeight: "32px",
109
+ fontSize: "24px"
110
+ },
111
+ children: data.name
112
+ })]
97
113
  }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_pricingTable.default, {
98
114
  table: data,
99
115
  onSelect: handleSelect
@@ -1,9 +1,10 @@
1
1
  /// <reference types="react" />
2
+ import { ChipOwnProps } from '@mui/material';
2
3
  type Props = {
3
4
  color?: string;
4
5
  backgroundColor?: string;
5
- };
6
- declare function Livemode({ color, backgroundColor }: Props): import("react").JSX.Element;
6
+ } & ChipOwnProps;
7
+ declare function Livemode({ color, backgroundColor, sx }: Props): import("react").JSX.Element;
7
8
  declare namespace Livemode {
8
9
  var defaultProps: {
9
10
  color: string;
@@ -9,7 +9,8 @@ var _context = require("@arcblock/ux/lib/Locale/context");
9
9
  var _material = require("@mui/material");
10
10
  function Livemode({
11
11
  color,
12
- backgroundColor
12
+ backgroundColor,
13
+ sx
13
14
  }) {
14
15
  const {
15
16
  t
@@ -26,7 +27,8 @@ function Livemode({
26
27
  fontWeight: "bold",
27
28
  borderRadius: "4px",
28
29
  backgroundColor,
29
- color
30
+ color,
31
+ ...sx
30
32
  }
31
33
  });
32
34
  }
@@ -79,13 +79,13 @@ function PricingTable({
79
79
  theme
80
80
  }) => theme.breakpoints.values.md}px) {
81
81
  .price-table-wrap:has(> div:nth-child(1)) {
82
- width: 320px !important;
82
+ max-width: 360px !important;
83
83
  }
84
84
  .price-table-wrap:has(> div:nth-child(2)) {
85
- width: 720px !important;
85
+ max-width: 720px !important;
86
86
  }
87
87
  .price-table-wrap:has(> div:nth-child(3)) {
88
- width: 960px !important;
88
+ max-width: 1080px !important;
89
89
  }
90
90
  .price-table-wrap:has(> div:nth-child(1)) > .price-table-item {
91
91
  width: 90% !important;
@@ -103,19 +103,22 @@ function PricingTable({
103
103
  direction: "column",
104
104
  alignItems: alignItems === "center" ? "center" : "flex-start",
105
105
  sx: {
106
- pt: {
107
- xs: 4,
108
- sm: 2
109
- },
110
106
  gap: {
111
107
  xs: 3,
112
108
  sm: mode === "select" ? 3 : 5
113
109
  }
114
110
  },
115
111
  children: [Object.keys(recurring).length > 1 && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.ToggleButtonGroup, {
116
- color: "primary",
117
112
  size: "small",
118
113
  value: state.interval,
114
+ sx: {
115
+ padding: "4px",
116
+ borderRadius: "36px",
117
+ height: "40px",
118
+ boxSizing: "border-box",
119
+ backgroundColor: "#f1f3f5",
120
+ border: 0
121
+ },
119
122
  onChange: (_, value) => {
120
123
  if (value !== null) {
121
124
  setState({
@@ -128,14 +131,22 @@ function PricingTable({
128
131
  size: "small",
129
132
  value: x,
130
133
  sx: {
131
- textTransform: "capitalize"
134
+ textTransform: "capitalize",
135
+ padding: "5px 12px",
136
+ fontSize: "13px",
137
+ backgroundColor: x === state.interval ? "#fff !important" : "#f1f3f5 !important",
138
+ border: "0px",
139
+ "&.Mui-selected": {
140
+ borderRadius: "9999px !important",
141
+ border: "1px solid #e5e7eb"
142
+ }
132
143
  },
133
144
  children: (0, _util.formatRecurring)(recurring[x], true, "", locale)
134
145
  }, x))
135
146
  }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, {
136
147
  flexWrap: "wrap",
137
148
  direction: "row",
138
- gap: "calc(10px + 3%)",
149
+ gap: "20px",
139
150
  justifyContent: alignItems === "center" ? "center" : "flex-start",
140
151
  className: "price-table-wrap",
141
152
  children: grouped[state.interval]?.map(x => {
@@ -147,7 +158,7 @@ function PricingTable({
147
158
  padding: 4,
148
159
  spacing: 2,
149
160
  direction: "column",
150
- alignItems: "center",
161
+ alignItems: "flex-start",
151
162
  className: "price-table-item",
152
163
  justifyContent: "flex-start",
153
164
  sx: {
@@ -155,81 +166,127 @@ function PricingTable({
155
166
  borderWidth: "1px",
156
167
  borderStyle: "solid",
157
168
  borderColor: mode === "select" && x.is_selected ? "primary.main" : "#eee",
158
- borderRadius: 1,
169
+ borderRadius: 2,
159
170
  transition: "border-color 0.3s ease 0s, box-shadow 0.3s ease 0s",
160
- boxShadow: "0 4px 8px rgba(0, 0, 0, 20%)",
171
+ boxShadow: "0px 0px 0px 1px rgba(3, 7, 18, 0.08), 0px 1px 2px -1px rgba(3, 7, 18, 0.08), 0px 2px 4px rgba(3, 7, 18, 0.04)",
161
172
  "&:hover": {
162
173
  borderColor: mode === "select" && x.is_selected ? "primary.main" : "#ddd",
163
174
  boxShadow: "0 8px 16px rgba(0, 0, 0, 20%)"
164
- }
175
+ },
176
+ padding: "20px",
177
+ position: "relative"
165
178
  },
166
- children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
179
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
167
180
  textAlign: "center",
168
- children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
169
- direction: "row",
170
- alignItems: "center",
171
- justifyContent: "center",
172
- spacing: 1,
173
- children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
174
- variant: "h5",
175
- color: "text.primary",
176
- fontWeight: 600,
177
- children: x.product.name
178
- }), x.is_highlight && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Chip, {
179
- label: x.highlight_text,
180
- color: "default",
181
- size: "small"
182
- })]
183
- }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
184
- color: "text.secondary",
185
- children: x.product.description
186
- })]
187
- }), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
188
- direction: "row",
189
- alignItems: "center",
190
- spacing: 1,
191
- children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_amount.default, {
192
- amount: (0, _util.formatPriceAmount)(x.price, table.currency, x.product.unit_label)
193
- }), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
181
+ children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
194
182
  direction: "column",
183
+ justifyContent: "center",
195
184
  alignItems: "flex-start",
196
- children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
197
- component: "span",
198
- color: "text.secondary",
199
- fontSize: "0.8rem",
200
- children: t("payment.checkout.per")
185
+ spacing: 1,
186
+ sx: {
187
+ gap: "12px"
188
+ },
189
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
190
+ sx: {
191
+ display: "flex",
192
+ alignItems: "center",
193
+ justifyContent: "space-between"
194
+ },
195
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
196
+ color: "text.primary",
197
+ fontWeight: 600,
198
+ sx: {
199
+ color: "#4B5563",
200
+ fontSize: "18px !important",
201
+ fontWeight: "600"
202
+ },
203
+ children: x.product.name
204
+ }), x.is_highlight && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Chip, {
205
+ label: x.highlight_text,
206
+ color: "default",
207
+ size: "small",
208
+ sx: {
209
+ position: "absolute",
210
+ top: "20px",
211
+ right: "20px"
212
+ }
213
+ })]
214
+ }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_amount.default, {
215
+ amount: (0, _util.formatPriceAmount)(x.price, table.currency, x.product.unit_label),
216
+ sx: {
217
+ my: 0,
218
+ marginTop: "0px !important",
219
+ fontSize: "48px",
220
+ fontWeight: "bold"
221
+ }
201
222
  }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
202
- component: "span",
203
223
  color: "text.secondary",
204
- fontSize: "0.8rem",
205
- children: (0, _util.formatRecurring)(x.price.recurring, false, "", locale)
224
+ sx: {
225
+ marginTop: "0px !important",
226
+ color: "#4b5563",
227
+ fontWeight: "400",
228
+ fontSize: "16px",
229
+ textAlign: "left"
230
+ },
231
+ children: x.product.description
206
232
  })]
207
- })]
208
- }), /* @__PURE__ */(0, _jsxRuntime.jsx)(Loading, {
209
- x,
210
- action,
211
- onSelect
212
- }), x.product.features.length > 0 && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
213
- children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
214
- children: t("payment.checkout.include")
215
- }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.List, {
233
+ })
234
+ }), x.product.features.length > 0 && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
235
+ sx: {
236
+ width: "100%"
237
+ },
238
+ children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.List, {
216
239
  dense: true,
217
- children: x.product.features.map(f => /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.ListItem, {
240
+ sx: {
241
+ display: "flex",
242
+ flexDirection: "column",
243
+ gap: "16px",
244
+ padding: "0px"
245
+ },
246
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
247
+ sx: {
248
+ width: "100%",
249
+ position: "relative",
250
+ borderTop: "1px solid #e5e7eb",
251
+ boxSizing: "border-box",
252
+ height: "1px"
253
+ }
254
+ }), x.product.features.map(f => /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.ListItem, {
218
255
  disableGutters: true,
219
256
  disablePadding: true,
257
+ sx: {
258
+ fontSize: "16px !important"
259
+ },
220
260
  children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.ListItemIcon, {
221
261
  sx: {
222
- minWidth: 25
262
+ minWidth: 25,
263
+ color: "#059669",
264
+ fontSize: "64px"
223
265
  },
224
266
  children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_iconsMaterial.CheckOutlined, {
225
267
  color: "success",
226
- fontSize: "small"
268
+ fontSize: "small",
269
+ sx: {
270
+ color: "#059669",
271
+ fontSize: "18px"
272
+ }
227
273
  })
228
274
  }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.ListItemText, {
275
+ sx: {
276
+ ".MuiListItemText-primary": {
277
+ fontSize: "16px",
278
+ color: "#030712",
279
+ fontWeight: "500"
280
+ }
281
+ },
229
282
  primary: f.name
230
283
  })]
231
- }, f.name))
232
- })]
284
+ }, f.name))]
285
+ })
286
+ }), /* @__PURE__ */(0, _jsxRuntime.jsx)(Subscribe, {
287
+ x,
288
+ action,
289
+ onSelect
233
290
  })]
234
291
  }, x?.price_id);
235
292
  })
@@ -237,7 +294,7 @@ function PricingTable({
237
294
  })
238
295
  });
239
296
  }
240
- function Loading({
297
+ function Subscribe({
241
298
  x,
242
299
  action,
243
300
  onSelect
@@ -260,11 +317,13 @@ function Loading({
260
317
  };
261
318
  return /* @__PURE__ */(0, _jsxRuntime.jsx)(_lab.LoadingButton, {
262
319
  fullWidth: true,
263
- size: "large",
264
- variant: x.is_highlight || x.is_selected ? "contained" : "outlined",
320
+ size: "medium",
321
+ variant: "contained",
265
322
  color: x.is_highlight || x.is_selected ? "primary" : "info",
266
323
  sx: {
267
- fontSize: "1.2rem"
324
+ fontSize: "16px",
325
+ padding: "10px 20px",
326
+ lineHeight: "28px"
268
327
  },
269
328
  loading: state.loading === x.price_id && !state.loaded,
270
329
  disabled: x.is_disabled,
package/lib/libs/util.js CHANGED
@@ -111,6 +111,9 @@ exports.formatLocale = formatLocale;
111
111
  const formatPrettyMsLocale = locale => locale === "zh" ? "zh_CN" : "en_US";
112
112
  exports.formatPrettyMsLocale = formatPrettyMsLocale;
113
113
  const formatError = err => {
114
+ if (!err) {
115
+ return "Unknown error";
116
+ }
114
117
  const {
115
118
  details,
116
119
  errors,
@@ -128,7 +131,7 @@ const formatError = err => {
128
131
  return `Validate failed: ${formatted.join(";")}`;
129
132
  }
130
133
  if (response) {
131
- return response.data.error || `${err.message}: ${JSON.stringify(response.data)}`;
134
+ return response.data?.error || `${err.message}: ${JSON.stringify(response.data)}`;
132
135
  }
133
136
  return err.message;
134
137
  };
@@ -1,8 +1,8 @@
1
1
  /// <reference types="react" />
2
+ import { TypographyProps } from '@mui/material';
2
3
  type Props = {
3
4
  amount: string;
4
- sx?: any;
5
- };
5
+ } & TypographyProps;
6
6
  declare function PaymentAmount({ amount, sx }: Props): import("react").JSX.Element;
7
7
  declare namespace PaymentAmount {
8
8
  var defaultProps: {
@@ -24,5 +24,6 @@ function PaymentAmount({
24
24
  });
25
25
  }
26
26
  PaymentAmount.defaultProps = {
27
+ // eslint-disable-next-line react/default-props-match-prop-types
27
28
  sx: {}
28
29
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/payment-react",
3
- "version": "1.13.260",
3
+ "version": "1.13.262",
4
4
  "description": "Reusable react components for payment kit v2",
5
5
  "keywords": [
6
6
  "react",
@@ -52,15 +52,15 @@
52
52
  }
53
53
  },
54
54
  "dependencies": {
55
- "@arcblock/did-connect": "^2.9.79",
56
- "@arcblock/ux": "^2.9.79",
57
- "@arcblock/ws": "^1.18.117",
58
- "@mui/icons-material": "^5.15.17",
55
+ "@arcblock/did-connect": "^2.9.80",
56
+ "@arcblock/ux": "^2.9.80",
57
+ "@arcblock/ws": "^1.18.120",
58
+ "@mui/icons-material": "^5.15.18",
59
59
  "@mui/lab": "^5.0.0-alpha.170",
60
- "@mui/material": "^5.15.17",
61
- "@mui/styles": "^5.15.17",
60
+ "@mui/material": "^5.15.18",
61
+ "@mui/styles": "^5.15.18",
62
62
  "@mui/system": "^5.15.15",
63
- "@ocap/util": "^1.18.117",
63
+ "@ocap/util": "^1.18.120",
64
64
  "@stripe/react-stripe-js": "^2.7.1",
65
65
  "@stripe/stripe-js": "^2.4.0",
66
66
  "@vitejs/plugin-legacy": "^5.4.0",
@@ -91,7 +91,7 @@
91
91
  "@babel/core": "^7.24.5",
92
92
  "@babel/preset-env": "^7.24.5",
93
93
  "@babel/preset-react": "^7.24.1",
94
- "@blocklet/payment-types": "1.13.260",
94
+ "@blocklet/payment-types": "1.13.262",
95
95
  "@storybook/addon-essentials": "^7.6.19",
96
96
  "@storybook/addon-interactions": "^7.6.19",
97
97
  "@storybook/addon-links": "^7.6.19",
@@ -120,5 +120,5 @@
120
120
  "vite-plugin-babel": "^1.2.0",
121
121
  "vite-plugin-node-polyfills": "^0.21.0"
122
122
  },
123
- "gitHead": "57b412a5be95152201bf70fe5a826984a277c4c9"
123
+ "gitHead": "223f9f888bc1cf70b8ed7ae367a5c27c341df6f3"
124
124
  }
@@ -73,11 +73,26 @@ export default function CheckoutTable({ id, mode, onPaid, onError, onChange, ext
73
73
  if (!sessionId && !hashSessionId) {
74
74
  if (mode === 'standalone') {
75
75
  return (
76
- <Stack direction="column" alignItems="center" spacing={4}>
77
- <Typography variant="h4" color="text.primary" fontWeight={600}>
78
- {data.name}
79
- {!data.livemode && <Livemode />}
80
- </Typography>
76
+ <Stack direction="column" alignItems="center">
77
+ <Box
78
+ sx={{
79
+ display: 'flex',
80
+ flexDirection: 'column',
81
+ fontSize: '24px',
82
+ margin: '20px 90px !important',
83
+ textAlign: 'center',
84
+ }}>
85
+ {!data.livemode && <Livemode sx={{ display: 'flex', marginBottom: '8px' }} />}
86
+ <Typography
87
+ color="text.primary"
88
+ fontWeight={600}
89
+ sx={{
90
+ lineHeight: '32px',
91
+ fontSize: '24px',
92
+ }}>
93
+ {data.name}
94
+ </Typography>
95
+ </Box>
81
96
  <PricingTable table={data} onSelect={handleSelect} />
82
97
  </Stack>
83
98
  );
@@ -1,12 +1,12 @@
1
1
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
2
- import { Chip } from '@mui/material';
2
+ import { Chip, ChipOwnProps } from '@mui/material';
3
3
 
4
4
  type Props = {
5
5
  color?: string;
6
6
  backgroundColor?: string;
7
- };
7
+ } & ChipOwnProps;
8
8
 
9
- export default function Livemode({ color, backgroundColor }: Props) {
9
+ export default function Livemode({ color, backgroundColor, sx }: Props) {
10
10
  const { t } = useLocaleContext();
11
11
  return (
12
12
  <Chip
@@ -22,6 +22,7 @@ export default function Livemode({ color, backgroundColor }: Props) {
22
22
  borderRadius: '4px',
23
23
  backgroundColor,
24
24
  color,
25
+ ...sx,
25
26
  }}
26
27
  />
27
28
  );
@@ -81,13 +81,13 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
81
81
  }
82
82
  @media (min-width: ${({ theme }) => theme.breakpoints.values.md}px) {
83
83
  .price-table-wrap:has(> div:nth-child(1)) {
84
- width: 320px !important;
84
+ max-width: 360px !important;
85
85
  }
86
86
  .price-table-wrap:has(> div:nth-child(2)) {
87
- width: 720px !important;
87
+ max-width: 720px !important;
88
88
  }
89
89
  .price-table-wrap:has(> div:nth-child(3)) {
90
- width: 960px !important;
90
+ max-width: 1080px !important;
91
91
  }
92
92
  .price-table-wrap:has(> div:nth-child(1)) > .price-table-item {
93
93
  width: 90% !important;
@@ -106,10 +106,6 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
106
106
  direction="column"
107
107
  alignItems={alignItems === 'center' ? 'center' : 'flex-start'}
108
108
  sx={{
109
- pt: {
110
- xs: 4,
111
- sm: 2,
112
- },
113
109
  gap: {
114
110
  xs: 3,
115
111
  sm: mode === 'select' ? 3 : 5,
@@ -117,9 +113,16 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
117
113
  }}>
118
114
  {Object.keys(recurring).length > 1 && (
119
115
  <ToggleButtonGroup
120
- color="primary"
121
116
  size="small"
122
117
  value={state.interval}
118
+ sx={{
119
+ padding: '4px',
120
+ borderRadius: '36px',
121
+ height: '40px',
122
+ boxSizing: 'border-box',
123
+ backgroundColor: '#f1f3f5',
124
+ border: 0,
125
+ }}
123
126
  onChange={(_, value) => {
124
127
  if (value !== null) {
125
128
  setState({ interval: value });
@@ -127,7 +130,21 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
127
130
  }}
128
131
  exclusive>
129
132
  {Object.keys(recurring).map((x) => (
130
- <ToggleButton size="small" key={x} value={x} sx={{ textTransform: 'capitalize' }}>
133
+ <ToggleButton
134
+ size="small"
135
+ key={x}
136
+ value={x}
137
+ sx={{
138
+ textTransform: 'capitalize',
139
+ padding: '5px 12px',
140
+ fontSize: '13px',
141
+ backgroundColor: x === state.interval ? '#fff !important' : '#f1f3f5 !important',
142
+ border: '0px',
143
+ '&.Mui-selected': {
144
+ borderRadius: '9999px !important',
145
+ border: '1px solid #e5e7eb',
146
+ },
147
+ }}>
131
148
  {formatRecurring(recurring[x] as PriceRecurring, true, '', locale)}
132
149
  </ToggleButton>
133
150
  ))}
@@ -136,12 +153,12 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
136
153
  <Stack
137
154
  flexWrap="wrap"
138
155
  direction="row"
139
- gap="calc(10px + 3%)"
156
+ gap="20px"
140
157
  justifyContent={alignItems === 'center' ? 'center' : 'flex-start'}
141
158
  className="price-table-wrap">
142
159
  {grouped[state.interval as string]?.map(
143
160
  (x: TPricingTableItem & { is_selected?: boolean; is_disabled?: boolean }) => {
144
- let action = x.subscription_data?.trial_period_days
161
+ let action: string = x.subscription_data?.trial_period_days
145
162
  ? t('payment.checkout.try')
146
163
  : t('payment.checkout.subscription');
147
164
  if (mode === 'select') {
@@ -154,7 +171,7 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
154
171
  padding={4}
155
172
  spacing={2}
156
173
  direction="column"
157
- alignItems="center"
174
+ alignItems="flex-start"
158
175
  className="price-table-item"
159
176
  justifyContent="flex-start"
160
177
  sx={{
@@ -162,50 +179,106 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
162
179
  borderWidth: '1px',
163
180
  borderStyle: 'solid',
164
181
  borderColor: mode === 'select' && x.is_selected ? 'primary.main' : '#eee',
165
- borderRadius: 1,
182
+ borderRadius: 2,
166
183
  transition: 'border-color 0.3s ease 0s, box-shadow 0.3s ease 0s',
167
- boxShadow: '0 4px 8px rgba(0, 0, 0, 20%)',
184
+ boxShadow:
185
+ '0px 0px 0px 1px rgba(3, 7, 18, 0.08), 0px 1px 2px -1px rgba(3, 7, 18, 0.08), 0px 2px 4px rgba(3, 7, 18, 0.04)',
168
186
  '&:hover': {
169
187
  borderColor: mode === 'select' && x.is_selected ? 'primary.main' : '#ddd',
170
188
  boxShadow: '0 8px 16px rgba(0, 0, 0, 20%)',
171
189
  },
190
+
191
+ padding: '20px',
192
+ position: 'relative',
172
193
  }}>
173
194
  <Box textAlign="center">
174
- <Stack direction="row" alignItems="center" justifyContent="center" spacing={1}>
175
- <Typography variant="h5" color="text.primary" fontWeight={600}>
176
- {x.product.name}
195
+ <Stack
196
+ direction="column"
197
+ justifyContent="center"
198
+ alignItems="flex-start"
199
+ spacing={1}
200
+ sx={{ gap: '12px' }}>
201
+ <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
202
+ <Typography
203
+ color="text.primary"
204
+ fontWeight={600}
205
+ sx={{
206
+ color: '#4B5563',
207
+ fontSize: '18px !important',
208
+ fontWeight: '600',
209
+ }}>
210
+ {x.product.name}
211
+ </Typography>
212
+ {x.is_highlight && (
213
+ <Chip
214
+ label={x.highlight_text}
215
+ color="default"
216
+ size="small"
217
+ sx={{
218
+ position: 'absolute',
219
+ top: '20px',
220
+ right: '20px',
221
+ }}
222
+ />
223
+ )}
224
+ </Box>
225
+ <Amount
226
+ amount={formatPriceAmount(x.price, table.currency, x.product.unit_label)}
227
+ sx={{ my: 0, marginTop: '0px !important', fontSize: '48px', fontWeight: 'bold' }}
228
+ />
229
+ <Typography
230
+ color="text.secondary"
231
+ sx={{
232
+ marginTop: '0px !important',
233
+ color: '#4b5563',
234
+ fontWeight: '400',
235
+ fontSize: '16px',
236
+ textAlign: 'left',
237
+ }}>
238
+ {x.product.description}
177
239
  </Typography>
178
- {x.is_highlight && <Chip label={x.highlight_text} color="default" size="small" />}
179
240
  </Stack>
180
- <Typography color="text.secondary">{x.product.description}</Typography>
181
241
  </Box>
182
- <Stack direction="row" alignItems="center" spacing={1}>
183
- <Amount amount={formatPriceAmount(x.price, table.currency, x.product.unit_label)} />
184
- <Stack direction="column" alignItems="flex-start">
185
- <Typography component="span" color="text.secondary" fontSize="0.8rem">
186
- {t('payment.checkout.per')}
187
- </Typography>
188
- <Typography component="span" color="text.secondary" fontSize="0.8rem">
189
- {formatRecurring(x.price.recurring as PriceRecurring, false, '', locale)}
190
- </Typography>
191
- </Stack>
192
- </Stack>
193
- <Loading x={x} action={action} onSelect={onSelect} />
194
242
  {x.product.features.length > 0 && (
195
- <Box>
196
- <Typography>{t('payment.checkout.include')}</Typography>
197
- <List dense>
243
+ <Box sx={{ width: '100%' }}>
244
+ <List dense sx={{ display: 'flex', flexDirection: 'column', gap: '16px', padding: '0px' }}>
245
+ <Box
246
+ sx={{
247
+ width: '100%',
248
+ position: 'relative',
249
+ borderTop: '1px solid #e5e7eb',
250
+ boxSizing: 'border-box',
251
+ height: '1px',
252
+ }}
253
+ />
198
254
  {x.product.features.map((f: any) => (
199
- <ListItem key={f.name} disableGutters disablePadding>
200
- <ListItemIcon sx={{ minWidth: 25 }}>
201
- <CheckOutlined color="success" fontSize="small" />
255
+ <ListItem key={f.name} disableGutters disablePadding sx={{ fontSize: '16px !important' }}>
256
+ <ListItemIcon sx={{ minWidth: 25, color: '#059669', fontSize: '64px' }}>
257
+ <CheckOutlined
258
+ color="success"
259
+ fontSize="small"
260
+ sx={{
261
+ color: '#059669',
262
+ fontSize: '18px',
263
+ }}
264
+ />
202
265
  </ListItemIcon>
203
- <ListItemText primary={f.name} />
266
+ <ListItemText
267
+ sx={{
268
+ '.MuiListItemText-primary': {
269
+ fontSize: '16px',
270
+ color: '#030712',
271
+ fontWeight: '500',
272
+ },
273
+ }}
274
+ primary={f.name}
275
+ />
204
276
  </ListItem>
205
277
  ))}
206
278
  </List>
207
279
  </Box>
208
280
  )}
281
+ <Subscribe x={x} action={action} onSelect={onSelect} />
209
282
  </Stack>
210
283
  );
211
284
  }
@@ -216,7 +289,7 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
216
289
  );
217
290
  }
218
291
 
219
- function Loading({ x, action, onSelect }: any) {
292
+ function Subscribe({ x, action, onSelect }: any) {
220
293
  const [state, setState] = useState({ loading: '', loaded: false });
221
294
 
222
295
  const handleSelect = async (priceId: string) => {
@@ -232,10 +305,10 @@ function Loading({ x, action, onSelect }: any) {
232
305
  return (
233
306
  <LoadingButton
234
307
  fullWidth
235
- size="large"
236
- variant={x.is_highlight || x.is_selected ? 'contained' : 'outlined'}
308
+ size="medium"
309
+ variant="contained"
237
310
  color={x.is_highlight || x.is_selected ? 'primary' : 'info'}
238
- sx={{ fontSize: '1.2rem' }}
311
+ sx={{ fontSize: '16px', padding: '10px 20px', lineHeight: '28px' }}
239
312
  loading={state.loading === x.price_id && !state.loaded}
240
313
  disabled={x.is_disabled}
241
314
  onClick={() => handleSelect(x.price_id)}
package/src/libs/util.ts CHANGED
@@ -96,6 +96,10 @@ export const formatLocale = (locale = 'en') => {
96
96
  export const formatPrettyMsLocale = (locale: string) => (locale === 'zh' ? 'zh_CN' : 'en_US');
97
97
 
98
98
  export const formatError = (err: any) => {
99
+ if (!err) {
100
+ return 'Unknown error';
101
+ }
102
+
99
103
  const { details, errors, response } = err;
100
104
 
101
105
  // graphql error
@@ -116,7 +120,7 @@ export const formatError = (err: any) => {
116
120
 
117
121
  // axios error
118
122
  if (response) {
119
- return response.data.error || `${err.message}: ${JSON.stringify(response.data)}`;
123
+ return response.data?.error || `${err.message}: ${JSON.stringify(response.data)}`;
120
124
  }
121
125
 
122
126
  return err.message;
@@ -1,6 +1,6 @@
1
- import { Typography } from '@mui/material';
1
+ import { Typography, TypographyProps } from '@mui/material';
2
2
 
3
- type Props = { amount: string; sx?: any };
3
+ type Props = { amount: string } & TypographyProps;
4
4
 
5
5
  export default function PaymentAmount({ amount, sx }: Props) {
6
6
  return (
@@ -20,5 +20,6 @@ export default function PaymentAmount({ amount, sx }: Props) {
20
20
  }
21
21
 
22
22
  PaymentAmount.defaultProps = {
23
+ // eslint-disable-next-line react/default-props-match-prop-types
23
24
  sx: {},
24
25
  };