@blocklet/payment-react 1.18.18 → 1.18.20

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.
@@ -6,6 +6,12 @@ import { useEffect, useRef } from "react";
6
6
  import { formatAmountPrecisionLimit } from "../libs/util.js";
7
7
  import { usePaymentContext } from "../contexts/payment.js";
8
8
  import { usePreventWheel } from "../hooks/scroll.js";
9
+ import { useTabNavigation } from "../hooks/keyboard.js";
10
+ const DONATION_PRESET_KEY_BASE = "payment-donation-preset";
11
+ const DONATION_CUSTOM_AMOUNT_KEY_BASE = "payment-donation-custom-amount";
12
+ const formatAmount = (amount) => {
13
+ return String(amount);
14
+ };
9
15
  export default function ProductDonation({
10
16
  item,
11
17
  settings,
@@ -13,40 +19,120 @@ export default function ProductDonation({
13
19
  currency
14
20
  }) {
15
21
  const { t, locale } = useLocaleContext();
16
- const { setPayable } = usePaymentContext();
22
+ const { setPayable, session } = usePaymentContext();
17
23
  usePreventWheel();
18
- const presets = settings?.amount?.presets || [];
19
- const preset = settings?.amount?.preset || presets?.[0] || "0";
24
+ const presets = (settings?.amount?.presets || []).map(formatAmount);
25
+ const getUserStorageKey = (base) => {
26
+ const userDid = session?.user?.did;
27
+ return userDid ? `${base}:${userDid}` : base;
28
+ };
29
+ const getSavedCustomAmount = () => {
30
+ try {
31
+ return localStorage.getItem(getUserStorageKey(DONATION_CUSTOM_AMOUNT_KEY_BASE)) || "";
32
+ } catch (e) {
33
+ console.warn("Failed to access localStorage", e);
34
+ return "";
35
+ }
36
+ };
37
+ const getDefaultPreset = () => {
38
+ if (settings?.amount?.preset) {
39
+ return formatAmount(settings.amount.preset);
40
+ }
41
+ try {
42
+ const savedPreset = localStorage.getItem(getUserStorageKey(DONATION_PRESET_KEY_BASE));
43
+ if (savedPreset) {
44
+ if (presets.includes(formatAmount(savedPreset))) {
45
+ return formatAmount(savedPreset);
46
+ }
47
+ if (savedPreset === "custom" && supportCustom) {
48
+ return "custom";
49
+ }
50
+ }
51
+ } catch (e) {
52
+ console.warn("Failed to access localStorage", e);
53
+ }
54
+ if (presets.length > 0) {
55
+ const middleIndex = Math.floor(presets.length / 2);
56
+ return presets[middleIndex] || presets[0];
57
+ }
58
+ return "0";
59
+ };
20
60
  const supportPreset = presets.length > 0;
21
61
  const supportCustom = !!settings?.amount?.custom;
62
+ const defaultPreset = getDefaultPreset();
63
+ const defaultCustomAmount = defaultPreset === "custom" ? getSavedCustomAmount() : "";
22
64
  const [state, setState] = useSetState({
23
- selected: preset,
24
- input: "",
25
- custom: !supportPreset,
65
+ selected: defaultPreset === "custom" ? "" : defaultPreset,
66
+ input: defaultCustomAmount,
67
+ custom: !supportPreset || defaultPreset === "custom",
26
68
  error: ""
27
69
  });
28
70
  const customInputRef = useRef(null);
71
+ const containerRef = useRef(null);
72
+ const handleSelect = (amount) => {
73
+ setPayable(true);
74
+ setState({ selected: formatAmount(amount), custom: false, error: "" });
75
+ onChange({ priceId: item.price_id, amount: formatAmount(amount) });
76
+ localStorage.setItem(getUserStorageKey(DONATION_PRESET_KEY_BASE), formatAmount(amount));
77
+ };
78
+ const handleCustomSelect = () => {
79
+ setState({ custom: true, selected: "", error: "" });
80
+ const savedCustomAmount = getSavedCustomAmount();
81
+ if (savedCustomAmount) {
82
+ setState({ input: savedCustomAmount });
83
+ onChange({ priceId: item.price_id, amount: savedCustomAmount });
84
+ setPayable(true);
85
+ } else if (!state.input) {
86
+ setPayable(false);
87
+ }
88
+ localStorage.setItem(getUserStorageKey(DONATION_PRESET_KEY_BASE), "custom");
89
+ };
90
+ const handleTabSelect = (selectedItem) => {
91
+ if (selectedItem === "custom") {
92
+ handleCustomSelect();
93
+ } else {
94
+ handleSelect(selectedItem);
95
+ }
96
+ };
97
+ const { handleKeyDown } = useTabNavigation(presets, handleTabSelect, {
98
+ includeCustom: supportCustom,
99
+ currentValue: state.custom ? void 0 : state.selected,
100
+ isCustomSelected: state.custom,
101
+ enabled: true,
102
+ selector: ".tab-navigable-card button",
103
+ containerRef
104
+ });
29
105
  useEffect(() => {
30
106
  if (settings.amount.preset) {
31
107
  setState({ selected: settings.amount.preset, custom: false });
32
108
  onChange({ priceId: item.price_id, amount: settings.amount.preset });
33
109
  } else if (settings.amount.presets && settings.amount.presets.length > 0) {
34
- setState({ selected: settings.amount.presets[0], custom: false });
35
- onChange({ priceId: item.price_id, amount: settings.amount.presets[0] });
110
+ const isCustom = defaultPreset === "custom";
111
+ setState({
112
+ selected: isCustom ? "" : defaultPreset,
113
+ custom: isCustom,
114
+ input: isCustom ? getSavedCustomAmount() : ""
115
+ });
116
+ if (!isCustom) {
117
+ onChange({ priceId: item.price_id, amount: defaultPreset });
118
+ } else if (defaultCustomAmount) {
119
+ onChange({ priceId: item.price_id, amount: defaultCustomAmount });
120
+ setPayable(true);
121
+ } else {
122
+ setPayable(false);
123
+ }
36
124
  }
37
125
  }, [settings.amount.preset, settings.amount.presets]);
38
126
  useEffect(() => {
127
+ if (containerRef.current) {
128
+ containerRef.current.focus();
129
+ }
39
130
  if (state.custom) {
40
131
  setTimeout(() => {
41
132
  customInputRef.current?.focus();
42
133
  }, 0);
43
134
  }
44
135
  }, [state.custom]);
45
- const handleSelect = (amount) => {
46
- setPayable(true);
47
- setState({ selected: amount, custom: false, error: "" });
48
- onChange({ priceId: item.price_id, amount });
49
- };
50
136
  const handleInput = (event) => {
51
137
  const { value } = event.target;
52
138
  const min = parseFloat(settings.amount.minimum || "0");
@@ -64,111 +150,133 @@ export default function ProductDonation({
64
150
  }
65
151
  setPayable(true);
66
152
  setState({ error: "", input: value });
67
- onChange({ priceId: item.price_id, amount: value });
68
- };
69
- const handleCustomSelect = () => {
70
- setState({ custom: true, error: "" });
71
- if (!state.input) {
72
- setPayable(false);
73
- }
153
+ onChange({ priceId: item.price_id, amount: formatAmount(value) });
154
+ localStorage.setItem(getUserStorageKey(DONATION_CUSTOM_AMOUNT_KEY_BASE), formatAmount(value));
74
155
  };
75
- return /* @__PURE__ */ jsxs(Box, { display: "flex", flexDirection: "column", alignItems: "flex-start", gap: 1.5, children: [
76
- supportPreset && /* @__PURE__ */ jsxs(Grid, { container: true, spacing: 2, children: [
77
- settings.amount.presets && settings.amount.presets.length > 0 && settings.amount.presets.map((amount) => /* @__PURE__ */ jsx(Grid, { item: true, xs: 6, sm: 3, children: /* @__PURE__ */ jsx(
78
- Card,
79
- {
80
- variant: "outlined",
81
- sx: {
82
- minWidth: 115,
83
- textAlign: "center",
84
- transition: "all 0.3s",
85
- cursor: "pointer",
86
- "&:hover": {
87
- transform: "translateY(-4px)",
88
- boxShadow: 3
89
- },
90
- height: "42px",
91
- ...state.selected === amount && !state.custom ? { borderColor: "primary.main", borderWidth: 1 } : {}
92
- },
93
- children: /* @__PURE__ */ jsx(CardActionArea, { onClick: () => handleSelect(amount), children: /* @__PURE__ */ jsxs(
94
- Stack,
156
+ return /* @__PURE__ */ jsxs(
157
+ Box,
158
+ {
159
+ ref: containerRef,
160
+ display: "flex",
161
+ flexDirection: "column",
162
+ alignItems: "flex-start",
163
+ gap: 1.5,
164
+ onKeyDown: handleKeyDown,
165
+ tabIndex: 0,
166
+ sx: { outline: "none" },
167
+ children: [
168
+ supportPreset && /* @__PURE__ */ jsxs(Grid, { container: true, spacing: 2, children: [
169
+ presets.map((amount) => /* @__PURE__ */ jsx(Grid, { item: true, xs: 6, sm: 3, children: /* @__PURE__ */ jsx(
170
+ Card,
95
171
  {
96
- direction: "row",
97
- sx: { py: 1.5, px: 1.5 },
98
- spacing: 0.5,
99
- alignItems: "center",
100
- justifyContent: "center",
101
- children: [
102
- /* @__PURE__ */ jsx(Avatar, { src: currency?.logo, sx: { width: 16, height: 16, mr: 0.5 }, alt: currency?.symbol }),
103
- /* @__PURE__ */ jsx(
104
- Typography,
105
- {
106
- component: "strong",
107
- lineHeight: 1,
108
- variant: "h3",
109
- sx: { fontVariantNumeric: "tabular-nums", fontWeight: 400 },
110
- children: amount
111
- }
112
- ),
113
- /* @__PURE__ */ jsx(Typography, { lineHeight: 1, fontSize: 14, color: "text.secondary", children: currency?.symbol })
114
- ]
172
+ variant: "outlined",
173
+ className: "tab-navigable-card",
174
+ sx: {
175
+ minWidth: 115,
176
+ textAlign: "center",
177
+ transition: "all 0.3s",
178
+ cursor: "pointer",
179
+ "&:hover": {
180
+ transform: "translateY(-4px)",
181
+ boxShadow: 3
182
+ },
183
+ ".MuiCardActionArea-focusHighlight": {
184
+ backgroundColor: "transparent"
185
+ },
186
+ height: "42px",
187
+ ...formatAmount(state.selected) === formatAmount(amount) && !state.custom ? { borderColor: "primary.main", borderWidth: 1 } : {}
188
+ },
189
+ children: /* @__PURE__ */ jsx(
190
+ CardActionArea,
191
+ {
192
+ onClick: () => handleSelect(amount),
193
+ tabIndex: 0,
194
+ "aria-selected": formatAmount(state.selected) === formatAmount(amount) && !state.custom,
195
+ children: /* @__PURE__ */ jsxs(
196
+ Stack,
197
+ {
198
+ direction: "row",
199
+ sx: { py: 1.5, px: 1.5 },
200
+ spacing: 0.5,
201
+ alignItems: "center",
202
+ justifyContent: "center",
203
+ children: [
204
+ /* @__PURE__ */ jsx(Avatar, { src: currency?.logo, sx: { width: 16, height: 16, mr: 0.5 }, alt: currency?.symbol }),
205
+ /* @__PURE__ */ jsx(
206
+ Typography,
207
+ {
208
+ component: "strong",
209
+ lineHeight: 1,
210
+ variant: "h3",
211
+ sx: { fontVariantNumeric: "tabular-nums", fontWeight: 400 },
212
+ children: amount
213
+ }
214
+ ),
215
+ /* @__PURE__ */ jsx(Typography, { lineHeight: 1, fontSize: 14, color: "text.secondary", children: currency?.symbol })
216
+ ]
217
+ }
218
+ )
219
+ }
220
+ )
115
221
  }
116
- ) })
117
- },
118
- amount
119
- ) }, amount)),
120
- supportCustom && /* @__PURE__ */ jsx(Grid, { item: true, xs: 6, sm: 3, children: /* @__PURE__ */ jsx(
121
- Card,
122
- {
123
- variant: "outlined",
124
- sx: {
125
- textAlign: "center",
126
- transition: "all 0.3s",
127
- cursor: "pointer",
128
- "&:hover": {
129
- transform: "translateY(-4px)",
130
- boxShadow: 3
131
- },
132
- height: "42px",
133
- ...state.custom ? { borderColor: "primary.main", borderWidth: 1 } : {}
134
- },
135
- children: /* @__PURE__ */ jsx(CardActionArea, { onClick: () => handleCustomSelect(), children: /* @__PURE__ */ jsx(
136
- Stack,
222
+ ) }, amount)),
223
+ supportCustom && /* @__PURE__ */ jsx(Grid, { item: true, xs: 6, sm: 3, children: /* @__PURE__ */ jsx(
224
+ Card,
137
225
  {
138
- direction: "row",
139
- sx: { py: 1.5, px: 1.5 },
140
- spacing: 0.5,
141
- alignItems: "center",
142
- justifyContent: "center",
143
- children: /* @__PURE__ */ jsx(Typography, { variant: "h3", lineHeight: 1, sx: { fontWeight: 400 }, children: t("common.custom") })
226
+ variant: "outlined",
227
+ className: "tab-navigable-card",
228
+ sx: {
229
+ textAlign: "center",
230
+ transition: "all 0.3s",
231
+ cursor: "pointer",
232
+ "&:hover": {
233
+ transform: "translateY(-4px)",
234
+ boxShadow: 3
235
+ },
236
+ ".MuiCardActionArea-focusHighlight": {
237
+ backgroundColor: "transparent"
238
+ },
239
+ height: "42px",
240
+ ...state.custom ? { borderColor: "primary.main", borderWidth: 1 } : {}
241
+ },
242
+ children: /* @__PURE__ */ jsx(CardActionArea, { onClick: handleCustomSelect, tabIndex: 0, "aria-selected": state.custom, children: /* @__PURE__ */ jsx(
243
+ Stack,
244
+ {
245
+ direction: "row",
246
+ sx: { py: 1.5, px: 1.5 },
247
+ spacing: 0.5,
248
+ alignItems: "center",
249
+ justifyContent: "center",
250
+ children: /* @__PURE__ */ jsx(Typography, { variant: "h3", lineHeight: 1, sx: { fontWeight: 400 }, children: t("common.custom") })
251
+ }
252
+ ) })
144
253
  }
145
- ) })
146
- },
147
- "custom"
148
- ) }, "custom")
149
- ] }),
150
- state.custom && /* @__PURE__ */ jsx(
151
- TextField,
152
- {
153
- type: "number",
154
- value: state.input,
155
- onChange: handleInput,
156
- margin: "none",
157
- fullWidth: true,
158
- error: !!state.error,
159
- helperText: state.error,
160
- inputRef: customInputRef,
161
- InputProps: {
162
- endAdornment: /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 0.5, alignItems: "center", sx: { ml: 1 }, children: [
163
- /* @__PURE__ */ jsx(Avatar, { src: currency?.logo, sx: { width: 16, height: 16 }, alt: currency?.symbol }),
164
- /* @__PURE__ */ jsx(Typography, { children: currency?.symbol })
165
- ] }),
166
- autoComplete: "off"
167
- },
168
- sx: {
169
- mt: preset !== "0" ? 0 : 1
170
- }
171
- }
172
- )
173
- ] });
254
+ ) }, "custom")
255
+ ] }),
256
+ state.custom && /* @__PURE__ */ jsx(
257
+ TextField,
258
+ {
259
+ type: "number",
260
+ value: state.input,
261
+ onChange: handleInput,
262
+ margin: "none",
263
+ fullWidth: true,
264
+ error: !!state.error,
265
+ helperText: state.error,
266
+ inputRef: customInputRef,
267
+ InputProps: {
268
+ endAdornment: /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 0.5, alignItems: "center", sx: { ml: 1 }, children: [
269
+ /* @__PURE__ */ jsx(Avatar, { src: currency?.logo, sx: { width: 16, height: 16 }, alt: currency?.symbol }),
270
+ /* @__PURE__ */ jsx(Typography, { children: currency?.symbol })
271
+ ] }),
272
+ autoComplete: "off"
273
+ },
274
+ sx: {
275
+ mt: defaultPreset !== "0" ? 0 : 1
276
+ }
277
+ }
278
+ )
279
+ ]
280
+ }
281
+ );
174
282
  }
@@ -21,8 +21,8 @@ function Livemode({
21
21
  color: "warning",
22
22
  sx: {
23
23
  ml: 2,
24
- height: 18,
25
- lineHeight: 1.2,
24
+ height: "18px",
25
+ lineHeight: "18px",
26
26
  textTransform: "uppercase",
27
27
  fontSize: "0.7rem",
28
28
  fontWeight: "bold",
@@ -0,0 +1,44 @@
1
+ import { KeyboardEvent, RefObject } from 'react';
2
+ type TabNavigationOptions<T> = {
3
+ /** whether to include custom option as the last item */
4
+ includeCustom?: boolean;
5
+ /** the value or index of the current selected item */
6
+ currentValue?: T | number;
7
+ /** whether the current selected item is custom */
8
+ isCustomSelected?: boolean;
9
+ /** a function to compare values, used to determine the current selected item */
10
+ compareValue?: (item: T, value: any) => boolean;
11
+ /** whether to allow Tab key navigation */
12
+ enabled?: boolean;
13
+ /** a selector to find navigable elements */
14
+ selector?: string;
15
+ /** an element container reference, limiting the query DOM range to improve performance */
16
+ containerRef?: RefObject<HTMLElement>;
17
+ /** the type of the current value, can be 'index' or 'value' */
18
+ valueType?: 'index' | 'value';
19
+ };
20
+ /**
21
+ * Tab key navigation hook - implement Tab key circular navigation between a set of options
22
+ *
23
+ * @param items an array of options, can be a simple type (string, number) array or an object array
24
+ * @param onSelect callback when an item is selected
25
+ * @param options configuration options
26
+ * @returns an object containing the event handler and control functions
27
+ *
28
+ * @example
29
+ * // simple string array
30
+ * const { handleKeyDown } = useTabNavigation(['10', '20', '50'], handleSelect);
31
+ *
32
+ * // object array
33
+ * const { handleKeyDown } = useTabNavigation(
34
+ * [{id: 1, name: 'A'}, {id: 2, name: 'B'}],
35
+ * handleSelect,
36
+ * { compareValue: (item, value) => item.id === value.id }
37
+ * );
38
+ */
39
+ export declare const useTabNavigation: <T>(items: T[], onSelect: (item: T | "custom", index: number) => void, options?: TabNavigationOptions<T>) => {
40
+ handleKeyDown: (e: KeyboardEvent) => void;
41
+ resetTabNavigation: () => void;
42
+ isTabNavigationActive: boolean;
43
+ };
44
+ export {};
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useTabNavigation = void 0;
7
+ var _react = require("react");
8
+ const useTabNavigation = (items, onSelect, options) => {
9
+ const {
10
+ valueType = "value",
11
+ includeCustom = false,
12
+ currentValue,
13
+ isCustomSelected = false,
14
+ compareValue = (item, value) => item === value,
15
+ enabled = true,
16
+ selector = ".tab-navigable-card button",
17
+ containerRef
18
+ } = options || {};
19
+ const hasTabbed = (0, _react.useRef)(false);
20
+ const findNavigableElements = (0, _react.useCallback)(() => {
21
+ if (containerRef?.current) {
22
+ return containerRef.current.querySelectorAll(selector);
23
+ }
24
+ return document.querySelectorAll(selector);
25
+ }, [containerRef, selector]);
26
+ const determineCurrentIndex = (0, _react.useCallback)(() => {
27
+ const allOptions = includeCustom ? [...items, "custom"] : items;
28
+ if (allOptions.length === 0) return -1;
29
+ if (!hasTabbed.current) {
30
+ if (isCustomSelected && includeCustom) {
31
+ return items.length;
32
+ }
33
+ if (currentValue !== void 0) {
34
+ if (valueType === "index" && typeof currentValue === "number") {
35
+ return currentValue >= 0 && currentValue < items.length ? currentValue : -1;
36
+ }
37
+ return items.findIndex(item => compareValue(item, currentValue));
38
+ }
39
+ } else {
40
+ const focusedElement = document.activeElement;
41
+ const navigableElements = findNavigableElements();
42
+ for (let i = 0; i < navigableElements.length; i++) {
43
+ if (navigableElements[i] === focusedElement) {
44
+ return i;
45
+ }
46
+ }
47
+ }
48
+ return -1;
49
+ }, [items, includeCustom, isCustomSelected, currentValue, valueType, compareValue, findNavigableElements]);
50
+ const getNextIndex = (0, _react.useCallback)((currentIndex, isShiftKey) => {
51
+ const totalOptions = includeCustom ? items.length + 1 : items.length;
52
+ if (currentIndex === -1) {
53
+ return 0;
54
+ }
55
+ if (isShiftKey) {
56
+ return currentIndex === 0 ? totalOptions - 1 : currentIndex - 1;
57
+ }
58
+ return currentIndex === totalOptions - 1 ? 0 : currentIndex + 1;
59
+ }, [items, includeCustom]);
60
+ const handleKeyDown = (0, _react.useCallback)(e => {
61
+ if (!enabled || e.key !== "Tab") return;
62
+ e.preventDefault();
63
+ e.stopPropagation();
64
+ const currentIndex = determineCurrentIndex();
65
+ const nextIndex = getNextIndex(currentIndex, e.shiftKey);
66
+ hasTabbed.current = true;
67
+ const selectedItem = nextIndex === items.length ? "custom" : items[nextIndex];
68
+ onSelect(selectedItem, nextIndex);
69
+ setTimeout(() => {
70
+ const elements = findNavigableElements();
71
+ if (elements[nextIndex]) {
72
+ elements[nextIndex].focus();
73
+ }
74
+ }, 0);
75
+ }, [items, onSelect, enabled, determineCurrentIndex, getNextIndex, findNavigableElements]);
76
+ const resetTabNavigation = (0, _react.useCallback)(() => {
77
+ hasTabbed.current = false;
78
+ }, []);
79
+ return {
80
+ handleKeyDown,
81
+ resetTabNavigation,
82
+ isTabNavigationActive: hasTabbed.current
83
+ };
84
+ };
85
+ exports.useTabNavigation = useTabNavigation;
package/lib/index.d.ts CHANGED
@@ -42,5 +42,6 @@ export * from './hooks/subscription';
42
42
  export * from './hooks/mobile';
43
43
  export * from './hooks/table';
44
44
  export * from './hooks/scroll';
45
+ export * from './hooks/keyboard';
45
46
  export { translations, createTranslator } from './locales';
46
47
  export { createLazyComponent, api, dayjs, FormInput, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, PricingItem, CountrySelect, Table, TruncatedText, Link, OverdueInvoicePayment, PaymentBeneficiaries, LoadingButton, DonateDetails, };
package/lib/index.js CHANGED
@@ -418,6 +418,18 @@ Object.keys(_scroll).forEach(function (key) {
418
418
  }
419
419
  });
420
420
  });
421
+ var _keyboard = require("./hooks/keyboard");
422
+ Object.keys(_keyboard).forEach(function (key) {
423
+ if (key === "default" || key === "__esModule") return;
424
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
425
+ if (key in exports && exports[key] === _keyboard[key]) return;
426
+ Object.defineProperty(exports, key, {
427
+ enumerable: true,
428
+ get: function () {
429
+ return _keyboard[key];
430
+ }
431
+ });
432
+ });
421
433
  var _locales = require("./locales");
422
434
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
423
435
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
package/lib/locales/en.js CHANGED
@@ -138,6 +138,7 @@ module.exports = (0, _flat.default)({
138
138
  empty: "No supporters yet",
139
139
  gaveTips: "{count} people gave tips",
140
140
  tipAmount: "Tip Amount",
141
+ tabHint: "to switch amount",
141
142
  benefits: {
142
143
  one: "{name} will receive all tips",
143
144
  multiple: "Tips will be distributed to {count} beneficiaries",
@@ -151,7 +152,7 @@ module.exports = (0, _flat.default)({
151
152
  later: "Configure Later",
152
153
  configTip: "Configure donation settings in Payment Kit"
153
154
  },
154
- cardPay: "{action} with card",
155
+ cardPay: "{action} with bank card",
155
156
  empty: "No thing to pay",
156
157
  per: "per",
157
158
  pay: "Pay {payee}",
@@ -168,7 +169,7 @@ module.exports = (0, _flat.default)({
168
169
  payment: "Thanks for your purchase",
169
170
  subscription: "Thanks for your subscribing",
170
171
  setup: "Thanks for your subscribing",
171
- donate: "Thanks for your support",
172
+ donate: "Thanks for your tip",
172
173
  tip: "A payment to {payee} has been completed. You can view the details of this payment in your account."
173
174
  },
174
175
  confirm: "Confirming allows {payee} to charge or reduce your staking. You can cancel or revoke staking anytime.",
package/lib/locales/zh.js CHANGED
@@ -138,6 +138,7 @@ module.exports = (0, _flat.default)({
138
138
  empty: "\u2764\uFE0F \u652F\u6301\u4E00\u4E0B",
139
139
  gaveTips: "\u5DF2\u6709 {count} \u4EBA\u6253\u8D4F",
140
140
  tipAmount: "\u6253\u8D4F\u91D1\u989D",
141
+ tabHint: "\u5FEB\u901F\u5207\u6362\u91D1\u989D",
141
142
  benefits: {
142
143
  one: "{name} \u5C06\u83B7\u5F97\u5168\u90E8\u6253\u8D4F",
143
144
  multiple: "\u6253\u8D4F\u5C06\u6309\u6BD4\u4F8B\u5206\u914D\u7ED9 {count} \u4F4D\u53D7\u76CA\u4EBA",
@@ -151,7 +152,7 @@ module.exports = (0, _flat.default)({
151
152
  later: "\u7A0D\u540E\u914D\u7F6E",
152
153
  configTip: "\u524D\u5F80 Payment Kit \u914D\u7F6E\u6253\u8D4F\u9009\u9879"
153
154
  },
154
- cardPay: "\u4F7F\u7528\u5361\u7247{action}",
155
+ cardPay: "\u4F7F\u7528\u94F6\u884C\u5361{action}",
155
156
  empty: "\u6CA1\u6709\u53EF\u652F\u4ED8\u7684\u9879\u76EE",
156
157
  per: "\u6BCF",
157
158
  pay: "\u4ED8\u6B3E\u7ED9 {payee}",
@@ -62,6 +62,9 @@ function PaymentInner({
62
62
  settings,
63
63
  session
64
64
  } = (0, _payment.usePaymentContext)();
65
+ const {
66
+ isMobile
67
+ } = (0, _mobile.useMobile)();
65
68
  const [state, setState] = (0, _ahooks.useSetState)({
66
69
  checkoutSession,
67
70
  submitting: false,
@@ -234,16 +237,48 @@ function PaymentInner({
234
237
  sx: {
235
238
  display: benefitsState.open ? "none" : "block"
236
239
  },
237
- children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
238
- title: t("payment.checkout.orderSummary"),
240
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
241
+ direction: "row",
242
+ justifyContent: "space-between",
243
+ alignItems: "center",
239
244
  sx: {
240
- color: "text.primary",
241
- fontSize: "18px",
242
- fontWeight: "500",
243
- lineHeight: "24px",
244
245
  mb: 2
245
246
  },
246
- children: t("payment.checkout.donation.tipAmount")
247
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
248
+ title: t("payment.checkout.orderSummary"),
249
+ sx: {
250
+ color: "text.primary",
251
+ fontSize: "18px",
252
+ fontWeight: "500",
253
+ lineHeight: "24px"
254
+ },
255
+ children: t("payment.checkout.donation.tipAmount")
256
+ }), !isMobile && donationSettings?.amount?.presets && donationSettings.amount.presets.length > 0 && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
257
+ sx: {
258
+ color: "text.secondary",
259
+ fontSize: "13px",
260
+ display: "flex",
261
+ alignItems: "center",
262
+ gap: 0.5,
263
+ opacity: 0.8
264
+ },
265
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
266
+ component: "span",
267
+ sx: {
268
+ border: "1px solid",
269
+ borderColor: "divider",
270
+ borderRadius: 0.75,
271
+ px: 0.75,
272
+ py: 0.25,
273
+ fontSize: "12px",
274
+ lineHeight: 1,
275
+ color: "text.secondary",
276
+ fontWeight: "400",
277
+ bgcolor: "transparent"
278
+ },
279
+ children: "Tab"
280
+ }), t("payment.checkout.donation.tabHint")]
281
+ })]
247
282
  }), items.map(x => /* @__PURE__ */(0, _jsxRuntime.jsx)(_productDonation.default, {
248
283
  item: x,
249
284
  settings: donationSettings,