@blocklet/payment-react 1.14.23 → 1.14.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/checkout/donate.js +26 -3
- package/es/libs/util.d.ts +15 -2
- package/es/libs/util.js +44 -9
- package/es/locales/en.js +3 -2
- package/es/locales/zh.js +3 -2
- package/es/payment/form/currency.js +0 -10
- package/es/payment/index.js +1 -14
- package/es/payment/product-donation.js +24 -14
- package/es/payment/product-item.d.ts +3 -1
- package/es/payment/product-item.js +8 -4
- package/es/payment/summary.d.ts +3 -1
- package/es/payment/summary.js +7 -3
- package/lib/checkout/donate.js +19 -4
- package/lib/libs/util.d.ts +15 -2
- package/lib/libs/util.js +61 -9
- package/lib/locales/en.js +3 -2
- package/lib/locales/zh.js +3 -2
- package/lib/payment/form/currency.js +0 -10
- package/lib/payment/index.js +1 -14
- package/lib/payment/product-donation.js +3 -2
- package/lib/payment/product-item.d.ts +3 -1
- package/lib/payment/product-item.js +11 -4
- package/lib/payment/summary.d.ts +3 -1
- package/lib/payment/summary.js +10 -3
- package/package.json +3 -3
- package/src/checkout/donate.tsx +25 -2
- package/src/libs/util.ts +53 -10
- package/src/locales/en.tsx +3 -2
- package/src/locales/zh.tsx +3 -2
- package/src/payment/form/currency.tsx +0 -10
- package/src/payment/index.tsx +2 -14
- package/src/payment/product-donation.tsx +7 -2
- package/src/payment/product-item.tsx +8 -3
- package/src/payment/summary.tsx +7 -2
package/lib/libs/util.js
CHANGED
|
@@ -28,6 +28,7 @@ exports.formatToDatetime = formatToDatetime;
|
|
|
28
28
|
exports.formatTotalPrice = formatTotalPrice;
|
|
29
29
|
exports.formatUpsellSaving = formatUpsellSaving;
|
|
30
30
|
exports.getCheckoutAmount = getCheckoutAmount;
|
|
31
|
+
exports.getFreeTrialTime = getFreeTrialTime;
|
|
31
32
|
exports.getInvoiceStatusColor = getInvoiceStatusColor;
|
|
32
33
|
exports.getPaymentIntentStatusColor = getPaymentIntentStatusColor;
|
|
33
34
|
exports.getPayoutStatusColor = getPayoutStatusColor;
|
|
@@ -266,7 +267,10 @@ function getPriceCurrencyOptions(price) {
|
|
|
266
267
|
tiers: null
|
|
267
268
|
}];
|
|
268
269
|
}
|
|
269
|
-
function formatLineItemPricing(item, currency,
|
|
270
|
+
function formatLineItemPricing(item, currency, {
|
|
271
|
+
trialEnd,
|
|
272
|
+
trialInDays
|
|
273
|
+
}, locale = "en") {
|
|
270
274
|
const price = item.upsell_price || item.price;
|
|
271
275
|
let quantity = (0, _locales.t)("common.qty", locale, {
|
|
272
276
|
count: item.quantity
|
|
@@ -277,6 +281,10 @@ function formatLineItemPricing(item, currency, trial, locale = "en") {
|
|
|
277
281
|
const unitValue = new _util.BN(getPriceUintAmountByCurrency(price, currency));
|
|
278
282
|
const total = `${(0, _util.fromUnitToToken)(unitValue.mul(new _util.BN(item.quantity)), currency.decimal)} ${currency.symbol}`;
|
|
279
283
|
const unit = `${(0, _util.fromUnitToToken)(unitValue, currency.decimal)} ${currency.symbol}`;
|
|
284
|
+
const trialResult = getFreeTrialTime({
|
|
285
|
+
trialInDays,
|
|
286
|
+
trialEnd
|
|
287
|
+
}, locale);
|
|
280
288
|
const appendUnit = (v, alt) => {
|
|
281
289
|
if (price.product.unit_label) {
|
|
282
290
|
return `${v}/${price.product.unit_label}`;
|
|
@@ -289,10 +297,11 @@ function formatLineItemPricing(item, currency, trial, locale = "en") {
|
|
|
289
297
|
}) : "";
|
|
290
298
|
};
|
|
291
299
|
if (price.type === "recurring" && price.recurring) {
|
|
292
|
-
if (
|
|
300
|
+
if (trialResult.count > 0) {
|
|
293
301
|
return {
|
|
294
302
|
primary: (0, _locales.t)("common.trial", locale, {
|
|
295
|
-
count:
|
|
303
|
+
count: trialResult.count,
|
|
304
|
+
interval: trialResult.interval
|
|
296
305
|
}),
|
|
297
306
|
secondary: `${appendUnit(total, total)} ${formatRecurring(price.recurring, false, "slash", locale)}`,
|
|
298
307
|
quantity
|
|
@@ -502,13 +511,54 @@ function formatPriceDisplay({
|
|
|
502
511
|
}
|
|
503
512
|
return [amount, then].filter(Boolean).join(" ");
|
|
504
513
|
}
|
|
505
|
-
function
|
|
514
|
+
function getFreeTrialTime({
|
|
515
|
+
trialInDays,
|
|
516
|
+
trialEnd
|
|
517
|
+
}, locale = "en") {
|
|
518
|
+
const now = (0, _dayjs.default)().unix();
|
|
519
|
+
if (trialEnd > 0 && trialEnd > now) {
|
|
520
|
+
if (trialEnd - now < 3600) {
|
|
521
|
+
return {
|
|
522
|
+
count: Math.ceil((trialEnd - now) / 60),
|
|
523
|
+
interval: (0, _locales.t)("common.minute", locale)
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
if (trialEnd - now < 86400) {
|
|
527
|
+
return {
|
|
528
|
+
count: Math.ceil((trialEnd - now) / 3600),
|
|
529
|
+
interval: (0, _locales.t)("common.hour", locale)
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
return {
|
|
533
|
+
count: Math.ceil((trialEnd - now) / 86400),
|
|
534
|
+
interval: (0, _locales.t)("common.day", locale)
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
if (trialInDays > 0) {
|
|
538
|
+
return {
|
|
539
|
+
count: trialInDays,
|
|
540
|
+
interval: (0, _locales.t)("common.day", locale)
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
return {
|
|
544
|
+
count: 0,
|
|
545
|
+
interval: (0, _locales.t)("common.day", locale)
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
function formatCheckoutHeadlines(items, currency, {
|
|
549
|
+
trialInDays,
|
|
550
|
+
trialEnd
|
|
551
|
+
}, locale = "en") {
|
|
506
552
|
const brand = getStatementDescriptor(items);
|
|
507
553
|
const {
|
|
508
554
|
total
|
|
509
555
|
} = getCheckoutAmount(items, currency, trialInDays > 0);
|
|
510
556
|
const actualAmount = (0, _util.fromUnitToToken)(total, currency.decimal);
|
|
511
557
|
const amount = `${(0, _util.fromUnitToToken)(total, currency.decimal)} ${currency.symbol}`;
|
|
558
|
+
const trialResult = getFreeTrialTime({
|
|
559
|
+
trialInDays,
|
|
560
|
+
trialEnd
|
|
561
|
+
}, locale);
|
|
512
562
|
if (items.length === 0) {
|
|
513
563
|
return {
|
|
514
564
|
action: (0, _locales.t)("payment.checkout.empty", locale),
|
|
@@ -551,17 +601,18 @@ function formatCheckoutHeadlines(items, currency, trialInDays, locale = "en") {
|
|
|
551
601
|
if (x.price.recurring?.usage_type === "metered") {
|
|
552
602
|
return acc;
|
|
553
603
|
}
|
|
554
|
-
return acc.add(new _util.BN(getPriceUintAmountByCurrency(x.price, currency)).mul(new _util.BN(x.quantity)));
|
|
604
|
+
return acc.add(new _util.BN(getPriceUintAmountByCurrency(x.upsell_price || x.price, currency)).mul(new _util.BN(x.quantity)));
|
|
555
605
|
}, new _util.BN(0)), currency.decimal), currency.symbol].filter(Boolean).join(" ");
|
|
556
606
|
if (items.length > 1) {
|
|
557
|
-
if (
|
|
607
|
+
if (trialResult.count > 0) {
|
|
558
608
|
const result4 = {
|
|
559
609
|
action: (0, _locales.t)("payment.checkout.try2", locale, {
|
|
560
610
|
name,
|
|
561
611
|
count: items.length - 1
|
|
562
612
|
}),
|
|
563
613
|
amount: (0, _locales.t)("payment.checkout.free", locale, {
|
|
564
|
-
count:
|
|
614
|
+
count: trialResult.count,
|
|
615
|
+
interval: trialResult.interval
|
|
565
616
|
}),
|
|
566
617
|
then: formatMeteredThen(subscription2, recurring, hasMetered && Number(subscription2) === 0, locale),
|
|
567
618
|
showThen: true,
|
|
@@ -589,13 +640,14 @@ function formatCheckoutHeadlines(items, currency, trialInDays, locale = "en") {
|
|
|
589
640
|
priceDisplay: formatPriceDisplay(result3, recurring, hasMetered, locale)
|
|
590
641
|
};
|
|
591
642
|
}
|
|
592
|
-
if (
|
|
643
|
+
if (trialResult.count > 0) {
|
|
593
644
|
const result3 = {
|
|
594
645
|
action: (0, _locales.t)("payment.checkout.try1", locale, {
|
|
595
646
|
name
|
|
596
647
|
}),
|
|
597
648
|
amount: (0, _locales.t)("payment.checkout.free", locale, {
|
|
598
|
-
count:
|
|
649
|
+
count: trialResult.count,
|
|
650
|
+
interval: trialResult.interval
|
|
599
651
|
}),
|
|
600
652
|
then: formatMeteredThen(subscription2, recurring, hasMetered && Number(subscription2) === 0, locale),
|
|
601
653
|
showThen: true,
|
package/lib/locales/en.js
CHANGED
|
@@ -67,9 +67,10 @@ module.exports = (0, _flat.default)({
|
|
|
67
67
|
continue: "Continue",
|
|
68
68
|
qty: "Qty {count}",
|
|
69
69
|
each: "{unit} each",
|
|
70
|
-
trial: "Free for {count}
|
|
70
|
+
trial: "Free for {count} {interval}{count > 1 ? 's' : ''}",
|
|
71
71
|
billed: "billed {rule}",
|
|
72
72
|
metered: "based on usage",
|
|
73
|
+
minute: "minute",
|
|
73
74
|
hour: "hour",
|
|
74
75
|
day: "day",
|
|
75
76
|
week: "week",
|
|
@@ -140,7 +141,7 @@ module.exports = (0, _flat.default)({
|
|
|
140
141
|
then: "Then {subscription} {recurring}",
|
|
141
142
|
meteredThen: "Then {recurring} based on usage",
|
|
142
143
|
metered: "{recurring} based on usage",
|
|
143
|
-
free: "{count}
|
|
144
|
+
free: "{count} {interval}{count > 1 ? 's' : ''} free",
|
|
144
145
|
least: "continue with at least",
|
|
145
146
|
completed: {
|
|
146
147
|
payment: "Thanks for your purchase",
|
package/lib/locales/zh.js
CHANGED
|
@@ -67,9 +67,10 @@ module.exports = (0, _flat.default)({
|
|
|
67
67
|
continue: "\u7EE7\u7EED",
|
|
68
68
|
qty: "{count} \u4EF6",
|
|
69
69
|
each: "\u6BCF\u4EF6 {unit}",
|
|
70
|
-
trial: "\u514D\u8D39\u8BD5\u7528 {count}
|
|
70
|
+
trial: "\u514D\u8D39\u8BD5\u7528 {count} {interval}",
|
|
71
71
|
billed: "{rule}\u6536\u8D39",
|
|
72
72
|
metered: "\u6309\u7528\u91CF",
|
|
73
|
+
minute: "\u5206\u949F",
|
|
73
74
|
hour: "\u5C0F\u65F6",
|
|
74
75
|
day: "\u5929",
|
|
75
76
|
week: "\u5468",
|
|
@@ -140,7 +141,7 @@ module.exports = (0, _flat.default)({
|
|
|
140
141
|
then: "\u7136\u540E {subscription} {recurring}",
|
|
141
142
|
meteredThen: "\u7136\u540E{recurring}\u6309\u7528\u91CF\u8BA1\u8D39",
|
|
142
143
|
metered: "{recurring}\u6309\u7528\u91CF\u8BA1\u8D39",
|
|
143
|
-
free: "\u514D\u8D39\u8BD5\u7528 {count}
|
|
144
|
+
free: "\u514D\u8D39\u8BD5\u7528 {count} {interval}",
|
|
144
145
|
least: "\u81F3\u5C11",
|
|
145
146
|
completed: {
|
|
146
147
|
payment: "\u611F\u8C22\u60A8\u7684\u8D2D\u4E70",
|
|
@@ -79,16 +79,6 @@ const Root = (0, _system.styled)("section")`
|
|
|
79
79
|
background: var(--backgrounds-bg-field, #f9fafb);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
// .cko-payment-card::before {
|
|
83
|
-
// content: '';
|
|
84
|
-
// position: absolute;
|
|
85
|
-
// right: 0;
|
|
86
|
-
// bottom: 0;
|
|
87
|
-
// border: 12px solid ${props => props.theme.palette.primary.main};
|
|
88
|
-
// border-top-color: transparent;
|
|
89
|
-
// border-left-color: transparent;
|
|
90
|
-
// }
|
|
91
|
-
|
|
92
82
|
.cko-payment-card-unselect {
|
|
93
83
|
border: 1px solid #ddd;
|
|
94
84
|
padding: 4px 8px;
|
package/lib/payment/index.js
CHANGED
|
@@ -194,6 +194,7 @@ function PaymentInner({
|
|
|
194
194
|
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_summary.default, {
|
|
195
195
|
items: state.checkoutSession.line_items,
|
|
196
196
|
trialInDays: state.checkoutSession.subscription_data?.trial_period_days || 0,
|
|
197
|
+
trialEnd: state.checkoutSession.subscription_data?.trial_end || 0,
|
|
197
198
|
billingThreshold: Math.max(state.checkoutSession.subscription_data?.billing_threshold_amount || 0,
|
|
198
199
|
// @ts-ignore
|
|
199
200
|
state.checkoutSession.subscription_data?.min_stake_amount || 0),
|
|
@@ -395,23 +396,18 @@ const Root = exports.Root = (0, _system.styled)(_material.Box)`
|
|
|
395
396
|
box-sizing: border-box;
|
|
396
397
|
display: flex;
|
|
397
398
|
flex-direction: column;
|
|
398
|
-
// justify-content: center;
|
|
399
399
|
align-items: center;
|
|
400
400
|
overflow: hidden;
|
|
401
|
-
// min-height: ${props => props.mode === "standalone" ? "100vh" : "auto"};
|
|
402
401
|
position: relative;
|
|
403
402
|
.cko-container {
|
|
404
403
|
overflow: hidden;
|
|
405
404
|
width: 100%;
|
|
406
|
-
// max-width: ${props => props.mode.endsWith("-minimal") ? "400px" : "1000px"};
|
|
407
405
|
display: flex;
|
|
408
406
|
flex-direction: row;
|
|
409
407
|
justify-content: center;
|
|
410
|
-
// gap: 4px;
|
|
411
408
|
position: relative;
|
|
412
409
|
flex: 1;
|
|
413
410
|
padding: 1px;
|
|
414
|
-
// padding: ${props => props.mode === "standalone" ? "0 16px" : "0"};
|
|
415
411
|
}
|
|
416
412
|
|
|
417
413
|
.base-card {
|
|
@@ -424,14 +420,11 @@ const Root = exports.Root = (0, _system.styled)(_material.Box)`
|
|
|
424
420
|
}
|
|
425
421
|
|
|
426
422
|
.cko-overview {
|
|
427
|
-
// width: ${props => props.mode.endsWith("-minimal") ? "100%" : "400px"};
|
|
428
|
-
// min-height: ${props => props.mode === "standalone" ? "540px" : "auto"};
|
|
429
423
|
position: relative;
|
|
430
424
|
flex-direction: column;
|
|
431
425
|
display: ${props => props.mode.endsWith("-minimal") ? "none" : "flex"};
|
|
432
426
|
background: var(--backgrounds-bg-base);
|
|
433
427
|
min-height: 'auto';
|
|
434
|
-
// width: 502px;
|
|
435
428
|
}
|
|
436
429
|
.cko-header {
|
|
437
430
|
left: 0;
|
|
@@ -459,8 +452,6 @@ const Root = exports.Root = (0, _system.styled)(_material.Box)`
|
|
|
459
452
|
|
|
460
453
|
.cko-payment {
|
|
461
454
|
width: 502px;
|
|
462
|
-
// width: ${props => props.mode.endsWith("-minimal") ? "100%" : "400px"};
|
|
463
|
-
// box-shadow: -4px 0px 8px 0px rgba(2, 7, 19, 0.04);
|
|
464
455
|
padding-left: ${props => props.mode === "standalone" ? "40px" : "20px"};
|
|
465
456
|
position: relative;
|
|
466
457
|
&:before {
|
|
@@ -485,10 +476,6 @@ const Root = exports.Root = (0, _system.styled)(_material.Box)`
|
|
|
485
476
|
}
|
|
486
477
|
|
|
487
478
|
.cko-payment-form {
|
|
488
|
-
// .MuiInputAdornment-positionStart {
|
|
489
|
-
// width: 50px;
|
|
490
|
-
// }
|
|
491
|
-
|
|
492
479
|
.MuiFormLabel-root {
|
|
493
480
|
color: var(--foregrounds-fg-base, #010714);
|
|
494
481
|
font-weight: 500;
|
|
@@ -151,7 +151,8 @@ function ProductDonation({
|
|
|
151
151
|
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
152
152
|
direction: "row",
|
|
153
153
|
sx: {
|
|
154
|
-
py: 1
|
|
154
|
+
py: 1,
|
|
155
|
+
px: 0.5
|
|
155
156
|
},
|
|
156
157
|
spacing: 0.5,
|
|
157
158
|
alignItems: "flex-end",
|
|
@@ -159,7 +160,7 @@ function ProductDonation({
|
|
|
159
160
|
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
160
161
|
component: "strong",
|
|
161
162
|
lineHeight: 1,
|
|
162
|
-
variant: "
|
|
163
|
+
variant: "h3",
|
|
163
164
|
sx: {
|
|
164
165
|
fontVariantNumeric: "tabular-nums",
|
|
165
166
|
fontWeight: 400
|
|
@@ -4,17 +4,19 @@ type Props = {
|
|
|
4
4
|
item: TLineItemExpanded;
|
|
5
5
|
items: TLineItemExpanded[];
|
|
6
6
|
trialInDays: number;
|
|
7
|
+
trialEnd?: number;
|
|
7
8
|
currency: TPaymentCurrency;
|
|
8
9
|
onUpsell: Function;
|
|
9
10
|
onDownsell: Function;
|
|
10
11
|
mode?: 'normal' | 'cross-sell';
|
|
11
12
|
children?: React.ReactNode;
|
|
12
13
|
};
|
|
13
|
-
declare function ProductItem({ item, items, trialInDays, currency, mode, children, onUpsell, onDownsell, }: Props): JSX.Element;
|
|
14
|
+
declare function ProductItem({ item, items, trialInDays, trialEnd, currency, mode, children, onUpsell, onDownsell, }: Props): JSX.Element;
|
|
14
15
|
declare namespace ProductItem {
|
|
15
16
|
var defaultProps: {
|
|
16
17
|
mode: string;
|
|
17
18
|
children: null;
|
|
19
|
+
trialEnd: number;
|
|
18
20
|
};
|
|
19
21
|
}
|
|
20
22
|
export default ProductItem;
|
|
@@ -12,15 +12,18 @@ var _status = _interopRequireDefault(require("../components/status"));
|
|
|
12
12
|
var _switchButton = _interopRequireDefault(require("../components/switch-button"));
|
|
13
13
|
var _util = require("../libs/util");
|
|
14
14
|
var _productCard = _interopRequireDefault(require("./product-card"));
|
|
15
|
+
var _dayjs = _interopRequireDefault(require("../libs/dayjs"));
|
|
15
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
16
17
|
ProductItem.defaultProps = {
|
|
17
18
|
mode: "normal",
|
|
18
|
-
children: null
|
|
19
|
+
children: null,
|
|
20
|
+
trialEnd: 0
|
|
19
21
|
};
|
|
20
22
|
function ProductItem({
|
|
21
23
|
item,
|
|
22
24
|
items,
|
|
23
25
|
trialInDays,
|
|
26
|
+
trialEnd = 0,
|
|
24
27
|
currency,
|
|
25
28
|
mode,
|
|
26
29
|
children,
|
|
@@ -31,18 +34,22 @@ function ProductItem({
|
|
|
31
34
|
t,
|
|
32
35
|
locale
|
|
33
36
|
} = (0, _context.useLocaleContext)();
|
|
34
|
-
const pricing = (0, _util.formatLineItemPricing)(item, currency,
|
|
37
|
+
const pricing = (0, _util.formatLineItemPricing)(item, currency, {
|
|
38
|
+
trialEnd,
|
|
39
|
+
trialInDays
|
|
40
|
+
}, locale);
|
|
35
41
|
const saving = (0, _util.formatUpsellSaving)(items, currency);
|
|
36
42
|
const metered = item.price?.recurring?.usage_type === "metered" ? t("common.metered") : "";
|
|
37
43
|
const canUpsell = mode === "normal" && items.length === 1;
|
|
38
44
|
const primaryText = (0, _react.useMemo)(() => {
|
|
39
45
|
const price = item.upsell_price || item.price || {};
|
|
40
46
|
const isRecurring = price?.type === "recurring" && price?.recurring;
|
|
41
|
-
|
|
47
|
+
const trial = trialInDays > 0 || trialEnd > (0, _dayjs.default)().unix();
|
|
48
|
+
if (isRecurring && !trial && price?.recurring?.usage_type !== "metered") {
|
|
42
49
|
return `${pricing.primary} ${price.recurring ? (0, _util.formatRecurring)(price.recurring, false, "slash", locale) : ""}`;
|
|
43
50
|
}
|
|
44
51
|
return pricing.primary;
|
|
45
|
-
}, [trialInDays, pricing, item, locale]);
|
|
52
|
+
}, [trialInDays, trialEnd, pricing, item, locale]);
|
|
46
53
|
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
47
54
|
direction: "column",
|
|
48
55
|
alignItems: "flex-start",
|
package/lib/payment/summary.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ type Props = {
|
|
|
4
4
|
items: TLineItemExpanded[];
|
|
5
5
|
currency: TPaymentCurrency;
|
|
6
6
|
trialInDays: number;
|
|
7
|
+
trialEnd?: number;
|
|
7
8
|
billingThreshold: number;
|
|
8
9
|
showStaking?: boolean;
|
|
9
10
|
onUpsell?: Function;
|
|
@@ -16,7 +17,7 @@ type Props = {
|
|
|
16
17
|
donationSettings?: DonationSettings;
|
|
17
18
|
action?: string;
|
|
18
19
|
};
|
|
19
|
-
declare function PaymentSummary({ items, currency, trialInDays, billingThreshold, onUpsell, onDownsell, onApplyCrossSell, onCancelCrossSell, onChangeAmount, checkoutSessionId, crossSellBehavior, showStaking, donationSettings, action, ...rest }: Props): import("react").JSX.Element;
|
|
20
|
+
declare function PaymentSummary({ items, currency, trialInDays, billingThreshold, onUpsell, onDownsell, onApplyCrossSell, onCancelCrossSell, onChangeAmount, checkoutSessionId, crossSellBehavior, showStaking, donationSettings, action, trialEnd, ...rest }: Props): import("react").JSX.Element;
|
|
20
21
|
declare namespace PaymentSummary {
|
|
21
22
|
var defaultProps: {
|
|
22
23
|
onUpsell: any;
|
|
@@ -29,6 +30,7 @@ declare namespace PaymentSummary {
|
|
|
29
30
|
showStaking: boolean;
|
|
30
31
|
donationSettings: null;
|
|
31
32
|
action: string;
|
|
33
|
+
trialEnd: number;
|
|
32
34
|
};
|
|
33
35
|
}
|
|
34
36
|
export default PaymentSummary;
|
package/lib/payment/summary.js
CHANGED
|
@@ -90,7 +90,8 @@ PaymentSummary.defaultProps = {
|
|
|
90
90
|
crossSellBehavior: "",
|
|
91
91
|
showStaking: false,
|
|
92
92
|
donationSettings: null,
|
|
93
|
-
action: ""
|
|
93
|
+
action: "",
|
|
94
|
+
trialEnd: 0
|
|
94
95
|
};
|
|
95
96
|
function PaymentSummary({
|
|
96
97
|
items,
|
|
@@ -107,6 +108,7 @@ function PaymentSummary({
|
|
|
107
108
|
showStaking,
|
|
108
109
|
donationSettings,
|
|
109
110
|
action,
|
|
111
|
+
trialEnd = 0,
|
|
110
112
|
...rest
|
|
111
113
|
}) {
|
|
112
114
|
const {
|
|
@@ -126,7 +128,10 @@ function PaymentSummary({
|
|
|
126
128
|
data,
|
|
127
129
|
runAsync
|
|
128
130
|
} = (0, _ahooks.useRequest)(() => checkoutSessionId ? fetchCrossSell(checkoutSessionId) : Promise.resolve(null));
|
|
129
|
-
const headlines = (0, _util2.formatCheckoutHeadlines)(items, currency,
|
|
131
|
+
const headlines = (0, _util2.formatCheckoutHeadlines)(items, currency, {
|
|
132
|
+
trialEnd,
|
|
133
|
+
trialInDays
|
|
134
|
+
}, locale);
|
|
130
135
|
const staking = showStaking ? getStakingSetup(items, currency, billingThreshold) : "0";
|
|
131
136
|
const totalAmount = (0, _util.fromUnitToToken)(new _util.BN((0, _util.fromTokenToUnit)(headlines.actualAmount, currency?.decimal)).add(new _util.BN(staking)).toString(), currency?.decimal);
|
|
132
137
|
(0, _useBus.default)("error.REQUIRE_CROSS_SELL", () => {
|
|
@@ -197,6 +202,7 @@ function PaymentSummary({
|
|
|
197
202
|
item: x,
|
|
198
203
|
items,
|
|
199
204
|
trialInDays,
|
|
205
|
+
trialEnd,
|
|
200
206
|
currency,
|
|
201
207
|
onUpsell: handleUpsell,
|
|
202
208
|
onDownsell: handleDownsell,
|
|
@@ -232,6 +238,7 @@ function PaymentSummary({
|
|
|
232
238
|
items,
|
|
233
239
|
trialInDays,
|
|
234
240
|
currency,
|
|
241
|
+
trialEnd,
|
|
235
242
|
onUpsell: _noop.default,
|
|
236
243
|
onDownsell: _noop.default,
|
|
237
244
|
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
@@ -289,7 +296,7 @@ function PaymentSummary({
|
|
|
289
296
|
},
|
|
290
297
|
children: action || t("payment.checkout.orderSummary")
|
|
291
298
|
}), !settings.livemode && /* @__PURE__ */(0, _jsxRuntime.jsx)(_livemode.default, {})]
|
|
292
|
-
}), isMobile ? /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
299
|
+
}), isMobile && !donationSettings ? /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
293
300
|
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
294
301
|
justifyContent: "space-between",
|
|
295
302
|
flexDirection: "row",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/payment-react",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.25",
|
|
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.
|
|
96
|
+
"@blocklet/payment-types": "1.14.25",
|
|
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": "
|
|
126
|
+
"gitHead": "d326f7f50aeb5a0b727b1eb1f5b042f82e2e4059"
|
|
127
127
|
}
|
package/src/checkout/donate.tsx
CHANGED
|
@@ -301,7 +301,16 @@ function useDonation(settings: DonationSettings, livemode: boolean = true, mode
|
|
|
301
301
|
};
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
-
function CheckoutDonateInner({
|
|
304
|
+
function CheckoutDonateInner({
|
|
305
|
+
settings,
|
|
306
|
+
livemode,
|
|
307
|
+
timeout,
|
|
308
|
+
onPaid,
|
|
309
|
+
onError,
|
|
310
|
+
mode,
|
|
311
|
+
inlineOptions = {},
|
|
312
|
+
theme,
|
|
313
|
+
}: DonateProps) {
|
|
305
314
|
// eslint-disable-line
|
|
306
315
|
const { state, setState, donation, supporters } = useDonation(settings, livemode, mode);
|
|
307
316
|
|
|
@@ -442,14 +451,28 @@ function CheckoutDonateInner({ settings, livemode, timeout, onPaid, onError, mod
|
|
|
442
451
|
maxWidth="md"
|
|
443
452
|
showCloseButton
|
|
444
453
|
disableEscapeKeyDown
|
|
454
|
+
sx={{
|
|
455
|
+
'.MuiDialogContent-root': {
|
|
456
|
+
padding: {
|
|
457
|
+
xs: 0,
|
|
458
|
+
md: '0 16px 0',
|
|
459
|
+
},
|
|
460
|
+
borderTop: '1px solid var(--stroke-border-base, #EFF1F5)',
|
|
461
|
+
width: {
|
|
462
|
+
xs: '100%',
|
|
463
|
+
md: 900,
|
|
464
|
+
},
|
|
465
|
+
},
|
|
466
|
+
}}
|
|
445
467
|
onClose={(e: any, reason: string) => setState({ open: reason === 'backdropClick' })}>
|
|
446
|
-
<Box sx={{
|
|
468
|
+
<Box sx={{ height: '100%', width: '100%' }}>
|
|
447
469
|
<CheckoutForm
|
|
448
470
|
id={donation.data?.id}
|
|
449
471
|
onPaid={handlePaid}
|
|
450
472
|
onError={onError}
|
|
451
473
|
action={settings.appearance?.button?.text}
|
|
452
474
|
mode="inline"
|
|
475
|
+
theme={theme}
|
|
453
476
|
/>
|
|
454
477
|
</Box>
|
|
455
478
|
</Dialog>
|
package/src/libs/util.ts
CHANGED
|
@@ -294,7 +294,7 @@ export function getPriceCurrencyOptions(price: TPrice): PriceCurrency[] {
|
|
|
294
294
|
export function formatLineItemPricing(
|
|
295
295
|
item: TLineItemExpanded,
|
|
296
296
|
currency: TPaymentCurrency,
|
|
297
|
-
|
|
297
|
+
{ trialEnd, trialInDays }: { trialEnd: number; trialInDays: number },
|
|
298
298
|
locale: string = 'en'
|
|
299
299
|
): { primary: string; secondary?: string; quantity: string } {
|
|
300
300
|
const price = item.upsell_price || item.price;
|
|
@@ -303,13 +303,14 @@ export function formatLineItemPricing(
|
|
|
303
303
|
if (price.recurring?.usage_type === 'metered' || +item.quantity === 1) {
|
|
304
304
|
quantity = '';
|
|
305
305
|
}
|
|
306
|
-
|
|
307
306
|
const unitValue = new BN(getPriceUintAmountByCurrency(price, currency));
|
|
308
307
|
|
|
309
308
|
const total = `${fromUnitToToken(unitValue.mul(new BN(item.quantity)), currency.decimal)} ${currency.symbol}`;
|
|
310
309
|
|
|
311
310
|
const unit = `${fromUnitToToken(unitValue, currency.decimal)} ${currency.symbol}`;
|
|
312
311
|
|
|
312
|
+
const trialResult = getFreeTrialTime({ trialInDays, trialEnd }, locale);
|
|
313
|
+
|
|
313
314
|
const appendUnit = (v: string, alt: string) => {
|
|
314
315
|
if (price.product.unit_label) {
|
|
315
316
|
return `${v}/${price.product.unit_label}`;
|
|
@@ -322,9 +323,9 @@ export function formatLineItemPricing(
|
|
|
322
323
|
};
|
|
323
324
|
|
|
324
325
|
if (price.type === 'recurring' && price.recurring) {
|
|
325
|
-
if (
|
|
326
|
+
if (trialResult.count > 0) {
|
|
326
327
|
return {
|
|
327
|
-
primary: t('common.trial', locale, { count:
|
|
328
|
+
primary: t('common.trial', locale, { count: trialResult.count, interval: trialResult.interval }),
|
|
328
329
|
secondary: `${appendUnit(total, total)} ${formatRecurring(price.recurring, false, 'slash', locale)}`,
|
|
329
330
|
quantity,
|
|
330
331
|
};
|
|
@@ -559,10 +560,48 @@ export function formatPriceDisplay(
|
|
|
559
560
|
}
|
|
560
561
|
return [amount, then].filter(Boolean).join(' ');
|
|
561
562
|
}
|
|
563
|
+
|
|
564
|
+
export function getFreeTrialTime(
|
|
565
|
+
{ trialInDays, trialEnd }: { trialInDays: number; trialEnd: number },
|
|
566
|
+
locale: string = 'en'
|
|
567
|
+
): {
|
|
568
|
+
count: number;
|
|
569
|
+
interval: string;
|
|
570
|
+
} {
|
|
571
|
+
const now = dayjs().unix();
|
|
572
|
+
if (trialEnd > 0 && trialEnd > now) {
|
|
573
|
+
if (trialEnd - now < 3600) {
|
|
574
|
+
return {
|
|
575
|
+
count: Math.ceil((trialEnd - now) / 60),
|
|
576
|
+
interval: t('common.minute', locale),
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
if (trialEnd - now < 86400) {
|
|
580
|
+
return {
|
|
581
|
+
count: Math.ceil((trialEnd - now) / 3600),
|
|
582
|
+
interval: t('common.hour', locale),
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
return {
|
|
586
|
+
count: Math.ceil((trialEnd - now) / 86400),
|
|
587
|
+
interval: t('common.day', locale),
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
if (trialInDays > 0) {
|
|
591
|
+
return {
|
|
592
|
+
count: trialInDays,
|
|
593
|
+
interval: t('common.day', locale),
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
return {
|
|
597
|
+
count: 0,
|
|
598
|
+
interval: t('common.day', locale),
|
|
599
|
+
};
|
|
600
|
+
}
|
|
562
601
|
export function formatCheckoutHeadlines(
|
|
563
602
|
items: TLineItemExpanded[],
|
|
564
603
|
currency: TPaymentCurrency,
|
|
565
|
-
trialInDays: number,
|
|
604
|
+
{ trialInDays, trialEnd }: { trialInDays: number; trialEnd: number },
|
|
566
605
|
locale: string = 'en'
|
|
567
606
|
): {
|
|
568
607
|
action: string;
|
|
@@ -577,6 +616,7 @@ export function formatCheckoutHeadlines(
|
|
|
577
616
|
const { total } = getCheckoutAmount(items, currency, trialInDays > 0);
|
|
578
617
|
const actualAmount = fromUnitToToken(total, currency.decimal);
|
|
579
618
|
const amount = `${fromUnitToToken(total, currency.decimal)} ${currency.symbol}`;
|
|
619
|
+
const trialResult = getFreeTrialTime({ trialInDays, trialEnd }, locale);
|
|
580
620
|
|
|
581
621
|
// empty
|
|
582
622
|
if (items.length === 0) {
|
|
@@ -618,7 +658,10 @@ export function formatCheckoutHeadlines(
|
|
|
618
658
|
if (x.price.recurring?.usage_type === 'metered') {
|
|
619
659
|
return acc;
|
|
620
660
|
}
|
|
621
|
-
|
|
661
|
+
|
|
662
|
+
return acc.add(
|
|
663
|
+
new BN(getPriceUintAmountByCurrency(x.upsell_price || x.price, currency)).mul(new BN(x.quantity))
|
|
664
|
+
);
|
|
622
665
|
}, new BN(0)),
|
|
623
666
|
currency.decimal
|
|
624
667
|
),
|
|
@@ -627,10 +670,10 @@ export function formatCheckoutHeadlines(
|
|
|
627
670
|
.filter(Boolean)
|
|
628
671
|
.join(' ');
|
|
629
672
|
if (items.length > 1) {
|
|
630
|
-
if (
|
|
673
|
+
if (trialResult.count > 0) {
|
|
631
674
|
const result = {
|
|
632
675
|
action: t('payment.checkout.try2', locale, { name, count: items.length - 1 }),
|
|
633
|
-
amount: t('payment.checkout.free', locale, { count:
|
|
676
|
+
amount: t('payment.checkout.free', locale, { count: trialResult.count, interval: trialResult.interval }),
|
|
634
677
|
then: formatMeteredThen(subscription, recurring, hasMetered && Number(subscription) === 0, locale),
|
|
635
678
|
showThen: true,
|
|
636
679
|
actualAmount: '0',
|
|
@@ -653,10 +696,10 @@ export function formatCheckoutHeadlines(
|
|
|
653
696
|
};
|
|
654
697
|
}
|
|
655
698
|
|
|
656
|
-
if (
|
|
699
|
+
if (trialResult.count > 0) {
|
|
657
700
|
const result = {
|
|
658
701
|
action: t('payment.checkout.try1', locale, { name }),
|
|
659
|
-
amount: t('payment.checkout.free', locale, { count:
|
|
702
|
+
amount: t('payment.checkout.free', locale, { count: trialResult.count, interval: trialResult.interval }),
|
|
660
703
|
then: formatMeteredThen(subscription, recurring, hasMetered && Number(subscription) === 0, locale),
|
|
661
704
|
showThen: true,
|
|
662
705
|
actualAmount: '0',
|
package/src/locales/en.tsx
CHANGED
|
@@ -62,9 +62,10 @@ export default flat({
|
|
|
62
62
|
continue: 'Continue',
|
|
63
63
|
qty: 'Qty {count}',
|
|
64
64
|
each: '{unit} each',
|
|
65
|
-
trial: "Free for {count}
|
|
65
|
+
trial: "Free for {count} {interval}{count > 1 ? 's' : ''}",
|
|
66
66
|
billed: 'billed {rule}',
|
|
67
67
|
metered: 'based on usage',
|
|
68
|
+
minute: 'minute',
|
|
68
69
|
hour: 'hour',
|
|
69
70
|
day: 'day',
|
|
70
71
|
week: 'week',
|
|
@@ -136,7 +137,7 @@ export default flat({
|
|
|
136
137
|
then: 'Then {subscription} {recurring}',
|
|
137
138
|
meteredThen: 'Then {recurring} based on usage',
|
|
138
139
|
metered: '{recurring} based on usage',
|
|
139
|
-
free: "{count}
|
|
140
|
+
free: "{count} {interval}{count > 1 ? 's' : ''} free",
|
|
140
141
|
least: 'continue with at least',
|
|
141
142
|
completed: {
|
|
142
143
|
payment: 'Thanks for your purchase',
|