@blocklet/payment-react 1.14.27 → 1.14.28

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.
@@ -70,7 +70,7 @@ export default function CheckoutForm({
70
70
  paymentLink: data?.paymentLink,
71
71
  customer: data?.customer,
72
72
  completed: state.completed,
73
- error: apiError || state.appError,
73
+ error: apiError,
74
74
  onPaid: handlePaid,
75
75
  onError: handleError,
76
76
  onChange,
@@ -91,7 +91,7 @@ export default function CheckoutForm({
91
91
  paymentLink: data?.paymentLink,
92
92
  customer: data?.customer,
93
93
  completed: state.completed,
94
- error: apiError || state.appError,
94
+ error: apiError,
95
95
  onPaid: handlePaid,
96
96
  onError: handleError,
97
97
  onChange,
@@ -111,7 +111,7 @@ export default function CheckoutForm({
111
111
  paymentLink: data?.paymentLink,
112
112
  customer: data?.customer,
113
113
  completed: state.completed,
114
- error: apiError || state.appError,
114
+ error: apiError,
115
115
  onPaid: handlePaid,
116
116
  onError: handleError,
117
117
  onChange,
@@ -65,7 +65,7 @@ function CheckoutTableInner({ id, mode, onPaid, onError, onChange, extraParams,
65
65
  }
66
66
  if (!sessionId && !hashSessionId) {
67
67
  if (mode === "standalone") {
68
- return /* @__PURE__ */ jsxs(Stack, { direction: "column", alignItems: "center", children: [
68
+ return /* @__PURE__ */ jsxs(Stack, { direction: "column", alignItems: "center", p: 2.5, children: [
69
69
  /* @__PURE__ */ jsxs(
70
70
  Box,
71
71
  {
@@ -73,11 +73,19 @@ function CheckoutTableInner({ id, mode, onPaid, onError, onChange, extraParams,
73
73
  display: "flex",
74
74
  flexDirection: "column",
75
75
  fontSize: "24px",
76
- margin: "20px 90px !important",
76
+ alignItems: "center",
77
+ margin: {
78
+ xs: "20px 0",
79
+ md: "20px 20px"
80
+ },
81
+ maxWidth: {
82
+ xs: "100%",
83
+ md: 400
84
+ },
77
85
  textAlign: "center"
78
86
  },
79
87
  children: [
80
- !data.livemode && /* @__PURE__ */ jsx(Livemode, { sx: { display: "flex", marginBottom: "8px" } }),
88
+ !data.livemode && /* @__PURE__ */ jsx(Livemode, { sx: { display: "flex", marginBottom: "8px", width: "fit-content" } }),
81
89
  /* @__PURE__ */ jsx(
82
90
  Typography,
83
91
  {
@@ -21,6 +21,7 @@ import { styled } from "@mui/system";
21
21
  import { useSetState } from "ahooks";
22
22
  import { useEffect, useMemo, useState } from "react";
23
23
  import { BN } from "@ocap/util";
24
+ import { isEmpty } from "lodash";
24
25
  import { usePaymentContext } from "../contexts/payment.js";
25
26
  import {
26
27
  formatError,
@@ -30,12 +31,19 @@ import {
30
31
  getPriceUintAmountByCurrency
31
32
  } from "../libs/util.js";
32
33
  import Amount from "../payment/amount.js";
34
+ import { useMobile } from "../hooks/mobile.js";
35
+ const sortOrder = {
36
+ year: 1,
37
+ month: 2,
38
+ day: 3,
39
+ hour: 4
40
+ };
33
41
  const groupItemsByRecurring = (items, currency) => {
34
42
  const grouped = {};
35
43
  const recurring = {};
36
44
  items.forEach((x) => {
37
45
  const key = [x.price.recurring?.interval, x.price.recurring?.interval_count].join("-");
38
- if (x.price.currency_options.find((c) => c.currency_id === currency.id)) {
46
+ if (x.price.currency_options?.find((c) => c.currency_id === currency.id)) {
39
47
  recurring[key] = x.price.recurring;
40
48
  }
41
49
  if (!grouped[key]) {
@@ -52,11 +60,28 @@ PricingTable.defaultProps = {
52
60
  };
53
61
  export default function PricingTable({ table, alignItems, interval, mode, onSelect }) {
54
62
  const { t, locale } = useLocaleContext();
63
+ const { isMobile } = useMobile();
55
64
  const {
56
65
  settings: { paymentMethods = [] }
57
66
  } = usePaymentContext();
58
67
  const [currency, setCurrency] = useState(table.currency || {});
59
68
  const { recurring, grouped } = useMemo(() => groupItemsByRecurring(table.items, currency), [table.items, currency]);
69
+ const recurringKeysList = useMemo(() => {
70
+ if (isEmpty(recurring)) {
71
+ return [];
72
+ }
73
+ return Object.keys(recurring).sort((a, b) => {
74
+ const [aType, aValue] = a.split("-");
75
+ const [bType, bValue] = b.split("-");
76
+ if (sortOrder[aType] !== sortOrder[bType]) {
77
+ return sortOrder[aType] - sortOrder[bType];
78
+ }
79
+ if (aValue && bValue) {
80
+ return bValue - aValue;
81
+ }
82
+ return b - a;
83
+ });
84
+ }, [recurring]);
60
85
  const [state, setState] = useSetState({ interval });
61
86
  const currencyMap = useMemo(() => {
62
87
  if (!paymentMethods || paymentMethods.length === 0) {
@@ -114,12 +139,12 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
114
139
  gap: 20px;
115
140
  }
116
141
  @media (max-width: ${({ theme }) => theme.breakpoints.values.sm}px) {
117
- .price-table-item {
118
- width: 90% !important;
119
- }
120
- .btn-row {
121
- padding: 0 20px;
122
- }
142
+ // .price-table-item {
143
+ // width: 90% !important;
144
+ // }
145
+ // .btn-row {
146
+ // padding: 0 20px;
147
+ // }
123
148
  }
124
149
  @media (min-width: ${({ theme }) => theme.breakpoints.values.md}px) {
125
150
  .price-table-wrap:has(> div:nth-child(1)) {
@@ -145,8 +170,17 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
145
170
  }
146
171
  },
147
172
  children: [
148
- /* @__PURE__ */ jsxs("div", { className: "btn-row", children: [
149
- Object.keys(recurring).length > 0 && /* @__PURE__ */ jsx(
173
+ /* @__PURE__ */ jsxs(Stack, { className: "btn-row", flexDirection: "row", children: [
174
+ recurringKeysList.length > 0 && /* @__PURE__ */ jsx(Box, { children: isMobile && recurringKeysList.length > 1 ? /* @__PURE__ */ jsx(
175
+ Select,
176
+ {
177
+ value: state.interval,
178
+ onChange: (e) => setState({ interval: e.target.value }),
179
+ size: "small",
180
+ sx: { m: 1 },
181
+ children: recurringKeysList.map((x) => /* @__PURE__ */ jsx(MenuItem, { value: x, children: /* @__PURE__ */ jsx(Typography, { color: x === state.interval ? "text.primary" : "text.secondary", children: formatRecurring(recurring[x], true, "", locale) }) }, x))
182
+ }
183
+ ) : /* @__PURE__ */ jsx(
150
184
  ToggleButtonGroup,
151
185
  {
152
186
  size: "small",
@@ -165,7 +199,7 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
165
199
  }
166
200
  },
167
201
  exclusive: true,
168
- children: Object.keys(recurring).map((x) => /* @__PURE__ */ jsx(
202
+ children: recurringKeysList.map((x) => /* @__PURE__ */ jsx(
169
203
  ToggleButton,
170
204
  {
171
205
  size: "small",
@@ -186,7 +220,7 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
186
220
  x
187
221
  ))
188
222
  }
189
- ),
223
+ ) }),
190
224
  currencyList.length > 0 && /* @__PURE__ */ jsx(
191
225
  Select,
192
226
  {
@@ -232,7 +266,10 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
232
266
  borderColor: mode === "select" && x.is_selected ? "primary.main" : "#ddd",
233
267
  boxShadow: "0 8px 16px rgba(0, 0, 0, 20%)"
234
268
  },
235
- width: "320px",
269
+ width: {
270
+ xs: "100%",
271
+ md: "320px"
272
+ },
236
273
  maxWidth: "360px",
237
274
  padding: "20px",
238
275
  position: "relative"
@@ -366,8 +403,12 @@ function Subscribe({ x, action, onSelect, currencyId }) {
366
403
  fullWidth: true,
367
404
  size: "medium",
368
405
  variant: "contained",
369
- color: x.is_highlight || x.is_selected ? "primary" : "info",
370
- sx: { fontSize: "16px", padding: "10px 20px", lineHeight: "28px" },
406
+ color: x.is_highlight || x.is_selected ? "info" : "primary",
407
+ sx: {
408
+ fontSize: "16px",
409
+ padding: "10px 20px",
410
+ lineHeight: "28px"
411
+ },
371
412
  loading: state.loading === x.price_id && !state.loaded,
372
413
  disabled: x.is_disabled,
373
414
  onClick: () => handleSelect(x.price_id),
package/es/libs/util.d.ts CHANGED
@@ -104,3 +104,4 @@ export declare function formatTotalPrice({ product, quantity, priceId, locale, }
104
104
  export declare function formatQuantityInventory(price: TPrice, quantity: string | number, locale?: string): string;
105
105
  export declare function formatSubscriptionStatus(status: string): string;
106
106
  export declare function formatAmountPrecisionLimit(amount: string, locale?: string, precision?: number): string;
107
+ export declare function getWordBreakStyle(value: any): 'break-word' | 'break-all';
package/es/libs/util.js CHANGED
@@ -799,3 +799,9 @@ export function formatAmountPrecisionLimit(amount, locale = "en", precision = 6)
799
799
  }
800
800
  return "";
801
801
  }
802
+ export function getWordBreakStyle(value) {
803
+ if (typeof value === "string" && /\s/.test(value)) {
804
+ return "break-word";
805
+ }
806
+ return "break-all";
807
+ }
package/es/locales/en.js CHANGED
@@ -193,7 +193,7 @@ export default flat({
193
193
  invoices: "Invoice History",
194
194
  details: "Details",
195
195
  summary: "Summary",
196
- specifics: "Specifics",
196
+ products: "Products",
197
197
  update: "Update Information",
198
198
  empty: "Seems you do not have any subscriptions or payments here",
199
199
  cancel: {
package/es/locales/zh.js CHANGED
@@ -110,9 +110,9 @@ export default flat({
110
110
  subscription: "\u67E5\u770B\u8BA2\u9605",
111
111
  invoice: "\u67E5\u770B\u8D26\u5355"
112
112
  },
113
- paymentRequired: "\u652F\u4ED8\u6570\u91CF",
113
+ paymentRequired: "\u652F\u4ED8\u91D1\u989D",
114
114
  staking: {
115
- title: "\u8D28\u62BC\u6570\u91CF",
115
+ title: "\u8D28\u62BC\u91D1\u989D",
116
116
  tooltip: "\u8D28\u62BC\u76F8\u5F53\u4E8E\u4FDD\u8BC1\u91D1\uFF0C\u7528\u4E8E\u786E\u4FDD\u672A\u6765\u7684\u8D26\u5355\u80FD\u591F\u6B63\u5E38\u6263\u6B3E\uFF0C\u5982\u679C\u4F60\u4ECE DID Wallet \u64A4\u9500\u8D28\u62BC\uFF0C\u8BA2\u9605\u4E5F\u4F1A\u88AB\u53D6\u6D88\u3002"
117
117
  },
118
118
  stakingConfirm: "\u5728\u6B64\u652F\u4ED8\u4E2D\uFF0C\u8D28\u62BC\u91D1\u989D\u4E0E\u4EA7\u54C1\u8D39\u7528\u5206\u5F00",
@@ -193,7 +193,7 @@ export default flat({
193
193
  invoices: "\u8D26\u5355\u5386\u53F2",
194
194
  details: "\u8D26\u6237\u8BE6\u60C5",
195
195
  summary: "\u8BA1\u8D39\u6458\u8981",
196
- specifics: "\u5177\u4F53\u4FE1\u606F",
196
+ products: "\u4EA7\u54C1\u4FE1\u606F",
197
197
  update: "\u66F4\u65B0\u5BA2\u6237\u4FE1\u606F",
198
198
  empty: "\u770B\u8D77\u6765\u60A8\u5728\u8FD9\u91CC\u6CA1\u6709\u4EFB\u4F55\u8BA2\u9605\u6216\u652F\u4ED8",
199
199
  cancel: {
@@ -23,7 +23,7 @@ export default function AddressForm({ mode, stripe, sx = {} }) {
23
23
  variant: "outlined",
24
24
  placeholder: t("payment.checkout.billing.postal_code"),
25
25
  InputProps: {
26
- startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx(
26
+ startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", style: { marginRight: "2px", marginLeft: "-8px" }, children: /* @__PURE__ */ jsx(
27
27
  Controller,
28
28
  {
29
29
  name: "billing_address.country",
@@ -6,7 +6,7 @@ type Props = CheckoutContext & CheckoutCallbacks & {
6
6
  error?: any;
7
7
  showCheckoutSummary?: boolean;
8
8
  };
9
- declare function Payment({ checkoutSession, paymentMethods, paymentIntent, paymentLink, customer, completed, mode, onPaid, onError, onChange, goBack, action, showCheckoutSummary, }: Props): import("react").JSX.Element;
9
+ declare function Payment({ checkoutSession, paymentMethods, paymentIntent, paymentLink, customer, completed, error, mode, onPaid, onError, onChange, goBack, action, showCheckoutSummary, }: Props): import("react").JSX.Element;
10
10
  declare namespace Payment {
11
11
  var defaultProps: {
12
12
  completed: boolean;
@@ -209,7 +209,7 @@ export default function Payment({
209
209
  paymentLink,
210
210
  customer,
211
211
  completed,
212
- // error,
212
+ error,
213
213
  mode,
214
214
  onPaid,
215
215
  onError,
@@ -238,6 +238,9 @@ export default function Payment({
238
238
  }
239
239
  }, [checkoutSession, livemode, setLivemode, refresh]);
240
240
  const renderContent = () => {
241
+ if (error) {
242
+ return /* @__PURE__ */ jsx(PaymentError, { mode, title: "Oops", description: formatError(error) });
243
+ }
241
244
  if (!checkoutSession || !delay) {
242
245
  return /* @__PURE__ */ jsxs(Stack, { className: "cko-container", sx: { gap: { sm: mode === "standalone" ? 0 : mode === "inline" ? 4 : 8 } }, children: [
243
246
  !hideSummaryCard && /* @__PURE__ */ jsx(Stack, { className: "base-card cko-overview", children: /* @__PURE__ */ jsx(Box, { className: "cko-product", children: /* @__PURE__ */ jsx(OverviewSkeleton, {}) }) }),
@@ -2,12 +2,9 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Fade, Skeleton, Stack, Typography } from "@mui/material";
3
3
  export default function OverviewSkeleton() {
4
4
  return /* @__PURE__ */ jsx(Fade, { in: true, children: /* @__PURE__ */ jsxs(Stack, { direction: "column", children: [
5
- /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 2, children: [
6
- /* @__PURE__ */ jsx(Skeleton, { variant: "circular", width: 32, height: 32 }),
7
- /* @__PURE__ */ jsx(Skeleton, { variant: "text", sx: { fontSize: "2rem", width: "40%" } })
8
- ] }),
5
+ /* @__PURE__ */ jsx(Stack, { direction: "row", alignItems: "center", spacing: 2, children: /* @__PURE__ */ jsx(Skeleton, { variant: "text", sx: { fontSize: "2rem", width: "40%" } }) }),
6
+ /* @__PURE__ */ jsx(Skeleton, { sx: { mt: 2 }, variant: "rounded", height: 100 }),
9
7
  /* @__PURE__ */ jsx(Typography, { mt: 2, component: "div", variant: "h4", children: /* @__PURE__ */ jsx(Skeleton, {}) }),
10
- /* @__PURE__ */ jsx(Typography, { component: "div", variant: "h2", children: /* @__PURE__ */ jsx(Skeleton, {}) }),
11
- /* @__PURE__ */ jsx(Skeleton, { sx: { mt: 2 }, variant: "rounded", width: 200, height: 200 })
8
+ /* @__PURE__ */ jsx(Typography, { component: "div", variant: "h2", children: /* @__PURE__ */ jsx(Skeleton, {}) })
12
9
  ] }) });
13
10
  }
@@ -1,16 +1,17 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Box, Fade, Skeleton, Stack, Typography } from "@mui/material";
3
3
  export default function PaymentSkeleton() {
4
- return /* @__PURE__ */ jsx(Fade, { in: true, children: /* @__PURE__ */ jsxs(Stack, { direction: "column", spacing: 2, children: [
4
+ return /* @__PURE__ */ jsx(Fade, { in: true, children: /* @__PURE__ */ jsxs(Stack, { direction: "column", children: [
5
5
  /* @__PURE__ */ jsx(Skeleton, { variant: "text", sx: { fontSize: "2rem", width: "40%" } }),
6
- /* @__PURE__ */ jsxs(Box, { children: [
7
- /* @__PURE__ */ jsx(Typography, { component: "div", variant: "h4", children: /* @__PURE__ */ jsx(Skeleton, {}) }),
8
- /* @__PURE__ */ jsx(Typography, { component: "div", variant: "h1", children: /* @__PURE__ */ jsx(Skeleton, {}) })
6
+ /* @__PURE__ */ jsx(Skeleton, { sx: { mt: 2 }, variant: "rounded", height: 68 }),
7
+ /* @__PURE__ */ jsxs(Box, { mt: 1, children: [
8
+ /* @__PURE__ */ jsx(Typography, { component: "div", variant: "h4", mb: -1, children: /* @__PURE__ */ jsx(Skeleton, {}) }),
9
+ /* @__PURE__ */ jsx(Typography, { component: "div", children: /* @__PURE__ */ jsx(Skeleton, { height: 60 }) })
9
10
  ] }),
10
11
  /* @__PURE__ */ jsxs(Box, { children: [
11
- /* @__PURE__ */ jsx(Typography, { component: "div", variant: "h4", children: /* @__PURE__ */ jsx(Skeleton, {}) }),
12
- /* @__PURE__ */ jsx(Typography, { component: "div", variant: "h1", children: /* @__PURE__ */ jsx(Skeleton, {}) })
12
+ /* @__PURE__ */ jsx(Typography, { component: "div", variant: "h4", mb: -1, children: /* @__PURE__ */ jsx(Skeleton, {}) }),
13
+ /* @__PURE__ */ jsx(Typography, { component: "div", children: /* @__PURE__ */ jsx(Skeleton, { height: 60 }) })
13
14
  ] }),
14
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Typography, { component: "div", variant: "h4", children: /* @__PURE__ */ jsx(Skeleton, {}) }) })
15
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Skeleton, { height: 60 }) })
15
16
  ] }) });
16
17
  }
@@ -81,7 +81,7 @@ function CheckoutForm({
81
81
  paymentLink: data?.paymentLink,
82
82
  customer: data?.customer,
83
83
  completed: state.completed,
84
- error: apiError || state.appError,
84
+ error: apiError,
85
85
  onPaid: handlePaid,
86
86
  onError: handleError,
87
87
  onChange,
@@ -101,7 +101,7 @@ function CheckoutForm({
101
101
  paymentLink: data?.paymentLink,
102
102
  customer: data?.customer,
103
103
  completed: state.completed,
104
- error: apiError || state.appError,
104
+ error: apiError,
105
105
  onPaid: handlePaid,
106
106
  onError: handleError,
107
107
  onChange,
@@ -120,7 +120,7 @@ function CheckoutForm({
120
120
  paymentLink: data?.paymentLink,
121
121
  customer: data?.customer,
122
122
  completed: state.completed,
123
- error: apiError || state.appError,
123
+ error: apiError,
124
124
  onPaid: handlePaid,
125
125
  onError: handleError,
126
126
  onChange,
@@ -99,18 +99,28 @@ function CheckoutTableInner({
99
99
  return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
100
100
  direction: "column",
101
101
  alignItems: "center",
102
+ p: 2.5,
102
103
  children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_system.Box, {
103
104
  sx: {
104
105
  display: "flex",
105
106
  flexDirection: "column",
106
107
  fontSize: "24px",
107
- margin: "20px 90px !important",
108
+ alignItems: "center",
109
+ margin: {
110
+ xs: "20px 0",
111
+ md: "20px 20px"
112
+ },
113
+ maxWidth: {
114
+ xs: "100%",
115
+ md: 400
116
+ },
108
117
  textAlign: "center"
109
118
  },
110
119
  children: [!data.livemode && /* @__PURE__ */(0, _jsxRuntime.jsx)(_livemode.default, {
111
120
  sx: {
112
121
  display: "flex",
113
- marginBottom: "8px"
122
+ marginBottom: "8px",
123
+ width: "fit-content"
114
124
  }
115
125
  }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
116
126
  color: "text.primary",
@@ -14,16 +14,24 @@ var _system = require("@mui/system");
14
14
  var _ahooks = require("ahooks");
15
15
  var _react = require("react");
16
16
  var _util = require("@ocap/util");
17
+ var _lodash = require("lodash");
17
18
  var _payment = require("../contexts/payment");
18
19
  var _util2 = require("../libs/util");
19
20
  var _amount = _interopRequireDefault(require("../payment/amount"));
21
+ var _mobile = require("../hooks/mobile");
20
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
+ const sortOrder = {
24
+ year: 1,
25
+ month: 2,
26
+ day: 3,
27
+ hour: 4
28
+ };
21
29
  const groupItemsByRecurring = (items, currency) => {
22
30
  const grouped = {};
23
31
  const recurring = {};
24
32
  items.forEach(x => {
25
33
  const key = [x.price.recurring?.interval, x.price.recurring?.interval_count].join("-");
26
- if (x.price.currency_options.find(c => c.currency_id === currency.id)) {
34
+ if (x.price.currency_options?.find(c => c.currency_id === currency.id)) {
27
35
  recurring[key] = x.price.recurring;
28
36
  }
29
37
  if (!grouped[key]) {
@@ -52,6 +60,9 @@ function PricingTable({
52
60
  t,
53
61
  locale
54
62
  } = (0, _context.useLocaleContext)();
63
+ const {
64
+ isMobile
65
+ } = (0, _mobile.useMobile)();
55
66
  const {
56
67
  settings: {
57
68
  paymentMethods = []
@@ -62,6 +73,22 @@ function PricingTable({
62
73
  recurring,
63
74
  grouped
64
75
  } = (0, _react.useMemo)(() => groupItemsByRecurring(table.items, currency), [table.items, currency]);
76
+ const recurringKeysList = (0, _react.useMemo)(() => {
77
+ if ((0, _lodash.isEmpty)(recurring)) {
78
+ return [];
79
+ }
80
+ return Object.keys(recurring).sort((a, b) => {
81
+ const [aType, aValue] = a.split("-");
82
+ const [bType, bValue] = b.split("-");
83
+ if (sortOrder[aType] !== sortOrder[bType]) {
84
+ return sortOrder[aType] - sortOrder[bType];
85
+ }
86
+ if (aValue && bValue) {
87
+ return bValue - aValue;
88
+ }
89
+ return b - a;
90
+ });
91
+ }, [recurring]);
65
92
  const [state, setState] = (0, _ahooks.useSetState)({
66
93
  interval
67
94
  });
@@ -127,12 +154,12 @@ function PricingTable({
127
154
  @media (max-width: ${({
128
155
  theme
129
156
  }) => theme.breakpoints.values.sm}px) {
130
- .price-table-item {
131
- width: 90% !important;
132
- }
133
- .btn-row {
134
- padding: 0 20px;
135
- }
157
+ // .price-table-item {
158
+ // width: 90% !important;
159
+ // }
160
+ // .btn-row {
161
+ // padding: 0 20px;
162
+ // }
136
163
  }
137
164
  @media (min-width: ${({
138
165
  theme
@@ -158,43 +185,62 @@ function PricingTable({
158
185
  sm: mode === "select" ? 3 : 5
159
186
  }
160
187
  },
161
- children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)("div", {
188
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
162
189
  className: "btn-row",
163
- children: [Object.keys(recurring).length > 0 && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.ToggleButtonGroup, {
164
- size: "small",
165
- value: state.interval,
166
- sx: {
167
- padding: "4px",
168
- borderRadius: "36px",
169
- height: "40px",
170
- boxSizing: "border-box",
171
- backgroundColor: "#f1f3f5",
172
- border: 0
173
- },
174
- onChange: (_, value) => {
175
- if (value !== null) {
176
- setState({
177
- interval: value
178
- });
179
- }
180
- },
181
- exclusive: true,
182
- children: Object.keys(recurring).map(x => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.ToggleButton, {
190
+ flexDirection: "row",
191
+ children: [recurringKeysList.length > 0 && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
192
+ children: isMobile && recurringKeysList.length > 1 ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Select, {
193
+ value: state.interval,
194
+ onChange: e => setState({
195
+ interval: e.target.value
196
+ }),
197
+ size: "small",
198
+ sx: {
199
+ m: 1
200
+ },
201
+ children: recurringKeysList.map(x => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.MenuItem, {
202
+ value: x,
203
+ children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
204
+ color: x === state.interval ? "text.primary" : "text.secondary",
205
+ children: (0, _util2.formatRecurring)(recurring[x], true, "", locale)
206
+ })
207
+ }, x))
208
+ }) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.ToggleButtonGroup, {
183
209
  size: "small",
184
- value: x,
210
+ value: state.interval,
185
211
  sx: {
186
- textTransform: "capitalize",
187
- padding: "5px 12px",
188
- fontSize: "13px",
189
- backgroundColor: x === state.interval ? "#fff !important" : "#f1f3f5 !important",
190
- border: "0px",
191
- "&.Mui-selected": {
192
- borderRadius: "9999px !important",
193
- border: "1px solid #e5e7eb"
212
+ padding: "4px",
213
+ borderRadius: "36px",
214
+ height: "40px",
215
+ boxSizing: "border-box",
216
+ backgroundColor: "#f1f3f5",
217
+ border: 0
218
+ },
219
+ onChange: (_, value) => {
220
+ if (value !== null) {
221
+ setState({
222
+ interval: value
223
+ });
194
224
  }
195
225
  },
196
- children: (0, _util2.formatRecurring)(recurring[x], true, "", locale)
197
- }, x))
226
+ exclusive: true,
227
+ children: recurringKeysList.map(x => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.ToggleButton, {
228
+ size: "small",
229
+ value: x,
230
+ sx: {
231
+ textTransform: "capitalize",
232
+ padding: "5px 12px",
233
+ fontSize: "13px",
234
+ backgroundColor: x === state.interval ? "#fff !important" : "#f1f3f5 !important",
235
+ border: "0px",
236
+ "&.Mui-selected": {
237
+ borderRadius: "9999px !important",
238
+ border: "1px solid #e5e7eb"
239
+ }
240
+ },
241
+ children: (0, _util2.formatRecurring)(recurring[x], true, "", locale)
242
+ }, x))
243
+ })
198
244
  }), currencyList.length > 0 && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Select, {
199
245
  value: currency?.id,
200
246
  onChange: e => setCurrency(currencyList.find(v => v?.id === e.target.value)),
@@ -241,7 +287,10 @@ function PricingTable({
241
287
  borderColor: mode === "select" && x.is_selected ? "primary.main" : "#ddd",
242
288
  boxShadow: "0 8px 16px rgba(0, 0, 0, 20%)"
243
289
  },
244
- width: "320px",
290
+ width: {
291
+ xs: "100%",
292
+ md: "320px"
293
+ },
245
294
  maxWidth: "360px",
246
295
  padding: "20px",
247
296
  position: "relative"
@@ -389,7 +438,7 @@ function Subscribe({
389
438
  fullWidth: true,
390
439
  size: "medium",
391
440
  variant: "contained",
392
- color: x.is_highlight || x.is_selected ? "primary" : "info",
441
+ color: x.is_highlight || x.is_selected ? "info" : "primary",
393
442
  sx: {
394
443
  fontSize: "16px",
395
444
  padding: "10px 20px",
@@ -104,3 +104,4 @@ export declare function formatTotalPrice({ product, quantity, priceId, locale, }
104
104
  export declare function formatQuantityInventory(price: TPrice, quantity: string | number, locale?: string): string;
105
105
  export declare function formatSubscriptionStatus(status: string): string;
106
106
  export declare function formatAmountPrecisionLimit(amount: string, locale?: string, precision?: number): string;
107
+ export declare function getWordBreakStyle(value: any): 'break-word' | 'break-all';
package/lib/libs/util.js CHANGED
@@ -43,6 +43,7 @@ exports.getSubscriptionAction = void 0;
43
43
  exports.getSubscriptionStatusColor = getSubscriptionStatusColor;
44
44
  exports.getTxLink = exports.getSubscriptionTimeSummary = void 0;
45
45
  exports.getWebhookStatusColor = getWebhookStatusColor;
46
+ exports.getWordBreakStyle = getWordBreakStyle;
46
47
  exports.isPaymentKitMounted = void 0;
47
48
  exports.isValidCountry = isValidCountry;
48
49
  exports.lazyLoad = lazyLoad;
@@ -967,4 +968,10 @@ function formatAmountPrecisionLimit(amount, locale = "en", precision = 6) {
967
968
  });
968
969
  }
969
970
  return "";
971
+ }
972
+ function getWordBreakStyle(value) {
973
+ if (typeof value === "string" && /\s/.test(value)) {
974
+ return "break-word";
975
+ }
976
+ return "break-all";
970
977
  }
package/lib/locales/en.js CHANGED
@@ -200,7 +200,7 @@ module.exports = (0, _flat.default)({
200
200
  invoices: "Invoice History",
201
201
  details: "Details",
202
202
  summary: "Summary",
203
- specifics: "Specifics",
203
+ products: "Products",
204
204
  update: "Update Information",
205
205
  empty: "Seems you do not have any subscriptions or payments here",
206
206
  cancel: {
package/lib/locales/zh.js CHANGED
@@ -117,9 +117,9 @@ module.exports = (0, _flat.default)({
117
117
  subscription: "\u67E5\u770B\u8BA2\u9605",
118
118
  invoice: "\u67E5\u770B\u8D26\u5355"
119
119
  },
120
- paymentRequired: "\u652F\u4ED8\u6570\u91CF",
120
+ paymentRequired: "\u652F\u4ED8\u91D1\u989D",
121
121
  staking: {
122
- title: "\u8D28\u62BC\u6570\u91CF",
122
+ title: "\u8D28\u62BC\u91D1\u989D",
123
123
  tooltip: "\u8D28\u62BC\u76F8\u5F53\u4E8E\u4FDD\u8BC1\u91D1\uFF0C\u7528\u4E8E\u786E\u4FDD\u672A\u6765\u7684\u8D26\u5355\u80FD\u591F\u6B63\u5E38\u6263\u6B3E\uFF0C\u5982\u679C\u4F60\u4ECE DID Wallet \u64A4\u9500\u8D28\u62BC\uFF0C\u8BA2\u9605\u4E5F\u4F1A\u88AB\u53D6\u6D88\u3002"
124
124
  },
125
125
  stakingConfirm: "\u5728\u6B64\u652F\u4ED8\u4E2D\uFF0C\u8D28\u62BC\u91D1\u989D\u4E0E\u4EA7\u54C1\u8D39\u7528\u5206\u5F00",
@@ -200,7 +200,7 @@ module.exports = (0, _flat.default)({
200
200
  invoices: "\u8D26\u5355\u5386\u53F2",
201
201
  details: "\u8D26\u6237\u8BE6\u60C5",
202
202
  summary: "\u8BA1\u8D39\u6458\u8981",
203
- specifics: "\u5177\u4F53\u4FE1\u606F",
203
+ products: "\u4EA7\u54C1\u4FE1\u606F",
204
204
  update: "\u66F4\u65B0\u5BA2\u6237\u4FE1\u606F",
205
205
  empty: "\u770B\u8D77\u6765\u60A8\u5728\u8FD9\u91CC\u6CA1\u6709\u4EFB\u4F55\u8BA2\u9605\u6216\u652F\u4ED8",
206
206
  cancel: {
@@ -52,6 +52,10 @@ function AddressForm({
52
52
  InputProps: {
53
53
  startAdornment: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.InputAdornment, {
54
54
  position: "start",
55
+ style: {
56
+ marginRight: "2px",
57
+ marginLeft: "-8px"
58
+ },
55
59
  children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_reactHookForm.Controller, {
56
60
  name: "billing_address.country",
57
61
  control,
@@ -6,7 +6,7 @@ type Props = CheckoutContext & CheckoutCallbacks & {
6
6
  error?: any;
7
7
  showCheckoutSummary?: boolean;
8
8
  };
9
- declare function Payment({ checkoutSession, paymentMethods, paymentIntent, paymentLink, customer, completed, mode, onPaid, onError, onChange, goBack, action, showCheckoutSummary, }: Props): import("react").JSX.Element;
9
+ declare function Payment({ checkoutSession, paymentMethods, paymentIntent, paymentLink, customer, completed, error, mode, onPaid, onError, onChange, goBack, action, showCheckoutSummary, }: Props): import("react").JSX.Element;
10
10
  declare namespace Payment {
11
11
  var defaultProps: {
12
12
  completed: boolean;
@@ -262,7 +262,7 @@ function Payment({
262
262
  paymentLink,
263
263
  customer,
264
264
  completed,
265
- // error,
265
+ error,
266
266
  mode,
267
267
  onPaid,
268
268
  onError,
@@ -297,6 +297,13 @@ function Payment({
297
297
  }
298
298
  }, [checkoutSession, livemode, setLivemode, refresh]);
299
299
  const renderContent = () => {
300
+ if (error) {
301
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_error.default, {
302
+ mode,
303
+ title: "Oops",
304
+ description: (0, _util2.formatError)(error)
305
+ });
306
+ }
300
307
  if (!checkoutSession || !delay) {
301
308
  return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
302
309
  className: "cko-container",
@@ -11,21 +11,23 @@ function OverviewSkeleton() {
11
11
  in: true,
12
12
  children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
13
13
  direction: "column",
14
- children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
14
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, {
15
15
  direction: "row",
16
16
  alignItems: "center",
17
17
  spacing: 2,
18
- children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
19
- variant: "circular",
20
- width: 32,
21
- height: 32
22
- }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
18
+ children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
23
19
  variant: "text",
24
20
  sx: {
25
21
  fontSize: "2rem",
26
22
  width: "40%"
27
23
  }
28
- })]
24
+ })
25
+ }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
26
+ sx: {
27
+ mt: 2
28
+ },
29
+ variant: "rounded",
30
+ height: 100
29
31
  }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
30
32
  mt: 2,
31
33
  component: "div",
@@ -35,13 +37,6 @@ function OverviewSkeleton() {
35
37
  component: "div",
36
38
  variant: "h2",
37
39
  children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {})
38
- }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
39
- sx: {
40
- mt: 2
41
- },
42
- variant: "rounded",
43
- width: 200,
44
- height: 200
45
40
  })]
46
41
  })
47
42
  });
@@ -11,38 +11,46 @@ function PaymentSkeleton() {
11
11
  in: true,
12
12
  children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
13
13
  direction: "column",
14
- spacing: 2,
15
14
  children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
16
15
  variant: "text",
17
16
  sx: {
18
17
  fontSize: "2rem",
19
18
  width: "40%"
20
19
  }
20
+ }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
21
+ sx: {
22
+ mt: 2
23
+ },
24
+ variant: "rounded",
25
+ height: 68
21
26
  }), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
27
+ mt: 1,
22
28
  children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
23
29
  component: "div",
24
30
  variant: "h4",
31
+ mb: -1,
25
32
  children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {})
26
33
  }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
27
34
  component: "div",
28
- variant: "h1",
29
- children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {})
35
+ children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
36
+ height: 60
37
+ })
30
38
  })]
31
39
  }), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
32
40
  children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
33
41
  component: "div",
34
42
  variant: "h4",
43
+ mb: -1,
35
44
  children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {})
36
45
  }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
37
46
  component: "div",
38
- variant: "h1",
39
- children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {})
47
+ children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
48
+ height: 60
49
+ })
40
50
  })]
41
51
  }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
42
- children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
43
- component: "div",
44
- variant: "h4",
45
- children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {})
52
+ children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
53
+ height: 60
46
54
  })
47
55
  })]
48
56
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/payment-react",
3
- "version": "1.14.27",
3
+ "version": "1.14.28",
4
4
  "description": "Reusable react components for payment kit v2",
5
5
  "keywords": [
6
6
  "react",
@@ -93,7 +93,7 @@
93
93
  "@babel/core": "^7.25.2",
94
94
  "@babel/preset-env": "^7.25.2",
95
95
  "@babel/preset-react": "^7.24.7",
96
- "@blocklet/payment-types": "1.14.27",
96
+ "@blocklet/payment-types": "1.14.28",
97
97
  "@storybook/addon-essentials": "^7.6.20",
98
98
  "@storybook/addon-interactions": "^7.6.20",
99
99
  "@storybook/addon-links": "^7.6.20",
@@ -123,5 +123,5 @@
123
123
  "vite-plugin-babel": "^1.2.0",
124
124
  "vite-plugin-node-polyfills": "^0.21.0"
125
125
  },
126
- "gitHead": "8a67ed1dbdda51526d4cd03c9c10c6930a9ac6a0"
126
+ "gitHead": "79178aa9251fb54006f6e0fe32a14619d1e8f06e"
127
127
  }
@@ -85,7 +85,7 @@ export default function CheckoutForm({
85
85
  paymentLink={data?.paymentLink}
86
86
  customer={data?.customer}
87
87
  completed={state.completed}
88
- error={apiError || state.appError}
88
+ error={apiError}
89
89
  onPaid={handlePaid}
90
90
  onError={handleError}
91
91
  onChange={onChange}
@@ -106,7 +106,7 @@ export default function CheckoutForm({
106
106
  paymentLink={data?.paymentLink}
107
107
  customer={data?.customer}
108
108
  completed={state.completed}
109
- error={apiError || state.appError}
109
+ error={apiError}
110
110
  onPaid={handlePaid}
111
111
  onError={handleError}
112
112
  onChange={onChange}
@@ -127,7 +127,7 @@ export default function CheckoutForm({
127
127
  paymentLink={data?.paymentLink}
128
128
  customer={data?.customer}
129
129
  completed={state.completed}
130
- error={apiError || state.appError}
130
+ error={apiError}
131
131
  onPaid={handlePaid}
132
132
  onError={handleError}
133
133
  onChange={onChange}
@@ -83,16 +83,24 @@ function CheckoutTableInner({ id, mode, onPaid, onError, onChange, extraParams,
83
83
  if (!sessionId && !hashSessionId) {
84
84
  if (mode === 'standalone') {
85
85
  return (
86
- <Stack direction="column" alignItems="center">
86
+ <Stack direction="column" alignItems="center" p={2.5}>
87
87
  <Box
88
88
  sx={{
89
89
  display: 'flex',
90
90
  flexDirection: 'column',
91
91
  fontSize: '24px',
92
- margin: '20px 90px !important',
92
+ alignItems: 'center',
93
+ margin: {
94
+ xs: '20px 0',
95
+ md: '20px 20px',
96
+ },
97
+ maxWidth: {
98
+ xs: '100%',
99
+ md: 400,
100
+ },
93
101
  textAlign: 'center',
94
102
  }}>
95
- {!data.livemode && <Livemode sx={{ display: 'flex', marginBottom: '8px' }} />}
103
+ {!data.livemode && <Livemode sx={{ display: 'flex', marginBottom: '8px', width: 'fit-content' }} />}
96
104
  <Typography
97
105
  color="text.primary"
98
106
  fontWeight={600}
@@ -23,6 +23,7 @@ import { useSetState } from 'ahooks';
23
23
  import { useEffect, useMemo, useState } from 'react';
24
24
 
25
25
  import { BN } from '@ocap/util';
26
+ import { isEmpty } from 'lodash';
26
27
  import { usePaymentContext } from '../contexts/payment';
27
28
  import {
28
29
  formatError,
@@ -32,6 +33,16 @@ import {
32
33
  getPriceUintAmountByCurrency,
33
34
  } from '../libs/util';
34
35
  import Amount from '../payment/amount';
36
+ import { useMobile } from '../hooks/mobile';
37
+
38
+ type SortOrder = { [key: string]: number };
39
+
40
+ const sortOrder: SortOrder = {
41
+ year: 1,
42
+ month: 2,
43
+ day: 3,
44
+ hour: 4,
45
+ };
35
46
 
36
47
  const groupItemsByRecurring = (items: TPricingTableItem[], currency: { id: string; symbol: string }) => {
37
48
  const grouped: { [key: string]: TPricingTableItem[] } = {};
@@ -39,7 +50,7 @@ const groupItemsByRecurring = (items: TPricingTableItem[], currency: { id: strin
39
50
 
40
51
  items.forEach((x) => {
41
52
  const key = [x.price.recurring?.interval, x.price.recurring?.interval_count].join('-');
42
- if (x.price.currency_options.find((c: PriceCurrency) => c.currency_id === currency.id)) {
53
+ if (x.price.currency_options?.find((c: PriceCurrency) => c.currency_id === currency.id)) {
43
54
  recurring[key] = x.price.recurring as PriceRecurring;
44
55
  }
45
56
  if (!grouped[key]) {
@@ -69,11 +80,30 @@ PricingTable.defaultProps = {
69
80
 
70
81
  export default function PricingTable({ table, alignItems, interval, mode, onSelect }: Props) {
71
82
  const { t, locale } = useLocaleContext();
83
+ const { isMobile } = useMobile();
72
84
  const {
73
85
  settings: { paymentMethods = [] },
74
86
  } = usePaymentContext();
75
87
  const [currency, setCurrency] = useState(table.currency || {});
76
88
  const { recurring, grouped } = useMemo(() => groupItemsByRecurring(table.items, currency), [table.items, currency]);
89
+ const recurringKeysList = useMemo(() => {
90
+ if (isEmpty(recurring)) {
91
+ return [];
92
+ }
93
+ return Object.keys(recurring).sort((a, b) => {
94
+ const [aType, aValue] = a.split('-');
95
+ const [bType, bValue] = b.split('-');
96
+ if (sortOrder[aType] !== sortOrder[bType]) {
97
+ return sortOrder[aType] - sortOrder[bType];
98
+ }
99
+ if (aValue && bValue) {
100
+ // @ts-ignore
101
+ return bValue - aValue;
102
+ }
103
+ // @ts-ignore
104
+ return b - a;
105
+ });
106
+ }, [recurring]);
77
107
  const [state, setState] = useSetState({ interval });
78
108
  const currencyMap = useMemo(() => {
79
109
  if (!paymentMethods || paymentMethods.length === 0) {
@@ -137,12 +167,12 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
137
167
  gap: 20px;
138
168
  }
139
169
  @media (max-width: ${({ theme }) => theme.breakpoints.values.sm}px) {
140
- .price-table-item {
141
- width: 90% !important;
142
- }
143
- .btn-row {
144
- padding: 0 20px;
145
- }
170
+ // .price-table-item {
171
+ // width: 90% !important;
172
+ // }
173
+ // .btn-row {
174
+ // padding: 0 20px;
175
+ // }
146
176
  }
147
177
  @media (min-width: ${({ theme }) => theme.breakpoints.values.md}px) {
148
178
  .price-table-wrap:has(> div:nth-child(1)) {
@@ -167,45 +197,63 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
167
197
  sm: mode === 'select' ? 3 : 5,
168
198
  },
169
199
  }}>
170
- <div className="btn-row">
171
- {Object.keys(recurring).length > 0 && (
172
- <ToggleButtonGroup
173
- size="small"
174
- value={state.interval}
175
- sx={{
176
- padding: '4px',
177
- borderRadius: '36px',
178
- height: '40px',
179
- boxSizing: 'border-box',
180
- backgroundColor: '#f1f3f5',
181
- border: 0,
182
- }}
183
- onChange={(_, value) => {
184
- if (value !== null) {
185
- setState({ interval: value });
186
- }
187
- }}
188
- exclusive>
189
- {Object.keys(recurring).map((x) => (
190
- <ToggleButton
200
+ <Stack className="btn-row" flexDirection="row">
201
+ {recurringKeysList.length > 0 && (
202
+ <Box>
203
+ {isMobile && recurringKeysList.length > 1 ? (
204
+ <Select
205
+ value={state.interval}
206
+ onChange={(e) => setState({ interval: e.target.value })}
191
207
  size="small"
192
- key={x}
193
- value={x}
208
+ sx={{ m: 1 }}>
209
+ {recurringKeysList.map((x) => (
210
+ <MenuItem key={x} value={x}>
211
+ <Typography color={x === state.interval ? 'text.primary' : 'text.secondary'}>
212
+ {formatRecurring(recurring[x] as PriceRecurring, true, '', locale)}
213
+ </Typography>
214
+ </MenuItem>
215
+ ))}
216
+ </Select>
217
+ ) : (
218
+ <ToggleButtonGroup
219
+ size="small"
220
+ value={state.interval}
194
221
  sx={{
195
- textTransform: 'capitalize',
196
- padding: '5px 12px',
197
- fontSize: '13px',
198
- backgroundColor: x === state.interval ? '#fff !important' : '#f1f3f5 !important',
199
- border: '0px',
200
- '&.Mui-selected': {
201
- borderRadius: '9999px !important',
202
- border: '1px solid #e5e7eb',
203
- },
204
- }}>
205
- {formatRecurring(recurring[x] as PriceRecurring, true, '', locale)}
206
- </ToggleButton>
207
- ))}
208
- </ToggleButtonGroup>
222
+ padding: '4px',
223
+ borderRadius: '36px',
224
+ height: '40px',
225
+ boxSizing: 'border-box',
226
+ backgroundColor: '#f1f3f5',
227
+ border: 0,
228
+ }}
229
+ onChange={(_, value) => {
230
+ if (value !== null) {
231
+ setState({ interval: value });
232
+ }
233
+ }}
234
+ exclusive>
235
+ {recurringKeysList.map((x) => (
236
+ <ToggleButton
237
+ size="small"
238
+ key={x}
239
+ value={x}
240
+ sx={{
241
+ textTransform: 'capitalize',
242
+ padding: '5px 12px',
243
+ fontSize: '13px',
244
+ backgroundColor: x === state.interval ? '#fff !important' : '#f1f3f5 !important',
245
+ border: '0px',
246
+ '&.Mui-selected': {
247
+ borderRadius: '9999px !important',
248
+ border: '1px solid #e5e7eb',
249
+ },
250
+ }}>
251
+ {formatRecurring(recurring[x] as PriceRecurring, true, '', locale)}
252
+ </ToggleButton>
253
+ ))}
254
+ </ToggleButtonGroup>
255
+ )}
256
+ </Box>
209
257
  )}
210
258
  {currencyList.length > 0 && (
211
259
  <Select
@@ -222,7 +270,7 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
222
270
  ))}
223
271
  </Select>
224
272
  )}
225
- </div>
273
+ </Stack>
226
274
  <Stack
227
275
  flexWrap="wrap"
228
276
  direction="row"
@@ -258,7 +306,10 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
258
306
  borderColor: mode === 'select' && x.is_selected ? 'primary.main' : '#ddd',
259
307
  boxShadow: '0 8px 16px rgba(0, 0, 0, 20%)',
260
308
  },
261
- width: '320px',
309
+ width: {
310
+ xs: '100%',
311
+ md: '320px',
312
+ },
262
313
  maxWidth: '360px',
263
314
 
264
315
  padding: '20px',
@@ -377,8 +428,12 @@ function Subscribe({ x, action, onSelect, currencyId }: any) {
377
428
  fullWidth
378
429
  size="medium"
379
430
  variant="contained"
380
- color={x.is_highlight || x.is_selected ? 'primary' : 'info'}
381
- sx={{ fontSize: '16px', padding: '10px 20px', lineHeight: '28px' }}
431
+ color={x.is_highlight || x.is_selected ? 'info' : 'primary'}
432
+ sx={{
433
+ fontSize: '16px',
434
+ padding: '10px 20px',
435
+ lineHeight: '28px',
436
+ }}
382
437
  loading={state.loading === x.price_id && !state.loaded}
383
438
  disabled={x.is_disabled}
384
439
  onClick={() => handleSelect(x.price_id)}
package/src/libs/util.ts CHANGED
@@ -1035,3 +1035,10 @@ export function formatAmountPrecisionLimit(amount: string, locale = 'en', precis
1035
1035
  }
1036
1036
  return '';
1037
1037
  }
1038
+
1039
+ export function getWordBreakStyle(value: any): 'break-word' | 'break-all' {
1040
+ if (typeof value === 'string' && /\s/.test(value)) {
1041
+ return 'break-word';
1042
+ }
1043
+ return 'break-all';
1044
+ }
@@ -198,7 +198,7 @@ export default flat({
198
198
  invoices: 'Invoice History',
199
199
  details: 'Details',
200
200
  summary: 'Summary',
201
- specifics: 'Specifics',
201
+ products: 'Products',
202
202
  update: 'Update Information',
203
203
  empty: 'Seems you do not have any subscriptions or payments here',
204
204
  cancel: {
@@ -112,9 +112,9 @@ export default flat({
112
112
  subscription: '查看订阅',
113
113
  invoice: '查看账单',
114
114
  },
115
- paymentRequired: '支付数量',
115
+ paymentRequired: '支付金额',
116
116
  staking: {
117
- title: '质押数量',
117
+ title: '质押金额',
118
118
  tooltip: '质押相当于保证金,用于确保未来的账单能够正常扣款,如果你从 DID Wallet 撤销质押,订阅也会被取消。',
119
119
  },
120
120
  stakingConfirm: '在此支付中,质押金额与产品费用分开',
@@ -195,7 +195,7 @@ export default flat({
195
195
  invoices: '账单历史',
196
196
  details: '账户详情',
197
197
  summary: '计费摘要',
198
- specifics: '具体信息',
198
+ products: '产品信息',
199
199
  update: '更新客户信息',
200
200
  empty: '看起来您在这里没有任何订阅或支付',
201
201
  cancel: {
@@ -33,7 +33,7 @@ export default function AddressForm({ mode, stripe, sx = {} }: Props) {
33
33
  placeholder={t('payment.checkout.billing.postal_code')}
34
34
  InputProps={{
35
35
  startAdornment: (
36
- <InputAdornment position="start">
36
+ <InputAdornment position="start" style={{ marginRight: '2px', marginLeft: '-8px' }}>
37
37
  <Controller
38
38
  name="billing_address.country"
39
39
  control={control}
@@ -248,7 +248,7 @@ export default function Payment({
248
248
  paymentLink,
249
249
  customer,
250
250
  completed,
251
- // error,
251
+ error,
252
252
  mode,
253
253
  onPaid,
254
254
  onError,
@@ -281,6 +281,9 @@ export default function Payment({
281
281
  }, [checkoutSession, livemode, setLivemode, refresh]);
282
282
 
283
283
  const renderContent = () => {
284
+ if (error) {
285
+ return <PaymentError mode={mode} title="Oops" description={formatError(error)} />;
286
+ }
284
287
  if (!checkoutSession || !delay) {
285
288
  return (
286
289
  <Stack className="cko-container" sx={{ gap: { sm: mode === 'standalone' ? 0 : mode === 'inline' ? 4 : 8 } }}>
@@ -5,16 +5,15 @@ 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="circular" width={32} height={32} />
9
8
  <Skeleton variant="text" sx={{ fontSize: '2rem', width: '40%' }} />
10
9
  </Stack>
10
+ <Skeleton sx={{ mt: 2 }} variant="rounded" height={100} />
11
11
  <Typography mt={2} component="div" variant="h4">
12
12
  <Skeleton />
13
13
  </Typography>
14
14
  <Typography component="div" variant="h2">
15
15
  <Skeleton />
16
16
  </Typography>
17
- <Skeleton sx={{ mt: 2 }} variant="rounded" width={200} height={200} />
18
17
  </Stack>
19
18
  </Fade>
20
19
  );
@@ -3,28 +3,27 @@ import { Box, Fade, Skeleton, Stack, Typography } from '@mui/material';
3
3
  export default function PaymentSkeleton() {
4
4
  return (
5
5
  <Fade in>
6
- <Stack direction="column" spacing={2}>
6
+ <Stack direction="column">
7
7
  <Skeleton variant="text" sx={{ fontSize: '2rem', width: '40%' }} />
8
- <Box>
9
- <Typography component="div" variant="h4">
8
+ <Skeleton sx={{ mt: 2 }} variant="rounded" height={68} />
9
+ <Box mt={1}>
10
+ <Typography component="div" variant="h4" mb={-1}>
10
11
  <Skeleton />
11
12
  </Typography>
12
- <Typography component="div" variant="h1">
13
- <Skeleton />
13
+ <Typography component="div">
14
+ <Skeleton height={60} />
14
15
  </Typography>
15
16
  </Box>
16
17
  <Box>
17
- <Typography component="div" variant="h4">
18
+ <Typography component="div" variant="h4" mb={-1}>
18
19
  <Skeleton />
19
20
  </Typography>
20
- <Typography component="div" variant="h1">
21
- <Skeleton />
21
+ <Typography component="div">
22
+ <Skeleton height={60} />
22
23
  </Typography>
23
24
  </Box>
24
25
  <Box>
25
- <Typography component="div" variant="h4">
26
- <Skeleton />
27
- </Typography>
26
+ <Skeleton height={60} />
28
27
  </Box>
29
28
  </Stack>
30
29
  </Fade>