@blocklet/payment-react 1.13.113

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.
Files changed (173) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +29 -0
  3. package/babel.config.es.js +8 -0
  4. package/build.config.ts +29 -0
  5. package/es/api.d.ts +2 -0
  6. package/es/api.js +18 -0
  7. package/es/checkout/index.d.ts +15 -0
  8. package/es/checkout/index.js +61 -0
  9. package/es/components/input.d.ts +23 -0
  10. package/es/components/input.js +44 -0
  11. package/es/components/livemode.d.ts +2 -0
  12. package/es/components/livemode.js +24 -0
  13. package/es/components/pricing-table.d.ts +18 -0
  14. package/es/components/pricing-table.js +175 -0
  15. package/es/components/status.d.ts +3 -0
  16. package/es/components/status.js +20 -0
  17. package/es/components/switch.d.ts +6 -0
  18. package/es/components/switch.js +42 -0
  19. package/es/contexts/payment.d.ts +29 -0
  20. package/es/contexts/payment.js +45 -0
  21. package/es/dayjs.d.ts +2 -0
  22. package/es/dayjs.js +14 -0
  23. package/es/index.d.ts +16 -0
  24. package/es/index.js +29 -0
  25. package/es/locales/en.d.ts +2 -0
  26. package/es/locales/en.js +213 -0
  27. package/es/locales/index.d.ts +10 -0
  28. package/es/locales/index.js +20 -0
  29. package/es/locales/zh.d.ts +2 -0
  30. package/es/locales/zh.js +213 -0
  31. package/es/payment/amount.d.ts +12 -0
  32. package/es/payment/amount.js +22 -0
  33. package/es/payment/error.d.ts +13 -0
  34. package/es/payment/error.js +12 -0
  35. package/es/payment/footer.d.ts +4 -0
  36. package/es/payment/footer.js +9 -0
  37. package/es/payment/form/addon.d.ts +2 -0
  38. package/es/payment/form/addon.js +14 -0
  39. package/es/payment/form/address.d.ts +7 -0
  40. package/es/payment/form/address.js +119 -0
  41. package/es/payment/form/index.d.ts +9 -0
  42. package/es/payment/form/index.js +337 -0
  43. package/es/payment/form/phone.d.ts +4 -0
  44. package/es/payment/form/phone.js +97 -0
  45. package/es/payment/form/stripe.d.ts +13 -0
  46. package/es/payment/form/stripe.js +158 -0
  47. package/es/payment/header.d.ts +7 -0
  48. package/es/payment/header.js +29 -0
  49. package/es/payment/index.d.ts +28 -0
  50. package/es/payment/index.js +327 -0
  51. package/es/payment/product-card.d.ts +21 -0
  52. package/es/payment/product-card.js +34 -0
  53. package/es/payment/product-item.d.ts +19 -0
  54. package/es/payment/product-item.js +107 -0
  55. package/es/payment/product-skeleton.d.ts +4 -0
  56. package/es/payment/product-skeleton.js +34 -0
  57. package/es/payment/skeleton/overview.d.ts +2 -0
  58. package/es/payment/skeleton/overview.js +13 -0
  59. package/es/payment/skeleton/payment.d.ts +2 -0
  60. package/es/payment/skeleton/payment.js +19 -0
  61. package/es/payment/success.d.ts +8 -0
  62. package/es/payment/success.js +164 -0
  63. package/es/payment/summary.d.ts +12 -0
  64. package/es/payment/summary.js +178 -0
  65. package/es/theme.d.ts +1 -0
  66. package/es/theme.js +17 -0
  67. package/es/types/index.d.ts +19 -0
  68. package/es/types/index.js +0 -0
  69. package/es/types/shims.d.ts +18 -0
  70. package/es/util.d.ts +52 -0
  71. package/es/util.js +390 -0
  72. package/lib/api.d.ts +2 -0
  73. package/lib/api.js +26 -0
  74. package/lib/checkout/index.d.ts +15 -0
  75. package/lib/checkout/index.js +83 -0
  76. package/lib/components/input.d.ts +23 -0
  77. package/lib/components/input.js +72 -0
  78. package/lib/components/livemode.d.ts +2 -0
  79. package/lib/components/livemode.js +29 -0
  80. package/lib/components/pricing-table.d.ts +18 -0
  81. package/lib/components/pricing-table.js +232 -0
  82. package/lib/components/status.d.ts +3 -0
  83. package/lib/components/status.js +23 -0
  84. package/lib/components/switch.d.ts +6 -0
  85. package/lib/components/switch.js +51 -0
  86. package/lib/contexts/payment.d.ts +29 -0
  87. package/lib/contexts/payment.js +73 -0
  88. package/lib/dayjs.d.ts +2 -0
  89. package/lib/dayjs.js +21 -0
  90. package/lib/index.d.ts +16 -0
  91. package/lib/index.js +143 -0
  92. package/lib/locales/en.d.ts +2 -0
  93. package/lib/locales/en.js +220 -0
  94. package/lib/locales/index.d.ts +10 -0
  95. package/lib/locales/index.js +33 -0
  96. package/lib/locales/zh.d.ts +2 -0
  97. package/lib/locales/zh.js +220 -0
  98. package/lib/payment/amount.d.ts +12 -0
  99. package/lib/payment/amount.js +28 -0
  100. package/lib/payment/error.d.ts +13 -0
  101. package/lib/payment/error.js +52 -0
  102. package/lib/payment/footer.d.ts +4 -0
  103. package/lib/payment/footer.js +25 -0
  104. package/lib/payment/form/addon.d.ts +2 -0
  105. package/lib/payment/form/addon.js +37 -0
  106. package/lib/payment/form/address.d.ts +7 -0
  107. package/lib/payment/form/address.js +152 -0
  108. package/lib/payment/form/index.d.ts +9 -0
  109. package/lib/payment/form/index.js +464 -0
  110. package/lib/payment/form/phone.d.ts +4 -0
  111. package/lib/payment/form/phone.js +133 -0
  112. package/lib/payment/form/stripe.d.ts +13 -0
  113. package/lib/payment/form/stripe.js +213 -0
  114. package/lib/payment/header.d.ts +7 -0
  115. package/lib/payment/header.js +58 -0
  116. package/lib/payment/index.d.ts +28 -0
  117. package/lib/payment/index.js +382 -0
  118. package/lib/payment/product-card.d.ts +21 -0
  119. package/lib/payment/product-card.js +81 -0
  120. package/lib/payment/product-item.d.ts +19 -0
  121. package/lib/payment/product-item.js +160 -0
  122. package/lib/payment/product-skeleton.d.ts +4 -0
  123. package/lib/payment/product-skeleton.js +71 -0
  124. package/lib/payment/skeleton/overview.d.ts +2 -0
  125. package/lib/payment/skeleton/overview.js +48 -0
  126. package/lib/payment/skeleton/payment.d.ts +2 -0
  127. package/lib/payment/skeleton/payment.js +54 -0
  128. package/lib/payment/success.d.ts +8 -0
  129. package/lib/payment/success.js +215 -0
  130. package/lib/payment/summary.d.ts +12 -0
  131. package/lib/payment/summary.js +225 -0
  132. package/lib/theme.d.ts +1 -0
  133. package/lib/theme.js +19 -0
  134. package/lib/types/index.d.ts +19 -0
  135. package/lib/types/index.js +1 -0
  136. package/lib/types/shims.d.ts +18 -0
  137. package/lib/util.d.ts +52 -0
  138. package/lib/util.js +487 -0
  139. package/package.json +104 -0
  140. package/src/api.ts +24 -0
  141. package/src/checkout/index.tsx +74 -0
  142. package/src/components/input.tsx +58 -0
  143. package/src/components/livemode.tsx +23 -0
  144. package/src/components/pricing-table.tsx +207 -0
  145. package/src/components/status.tsx +19 -0
  146. package/src/components/switch.tsx +48 -0
  147. package/src/contexts/payment.tsx +74 -0
  148. package/src/dayjs.ts +17 -0
  149. package/src/index.ts +32 -0
  150. package/src/locales/en.tsx +218 -0
  151. package/src/locales/index.tsx +30 -0
  152. package/src/locales/zh.tsx +214 -0
  153. package/src/payment/amount.tsx +24 -0
  154. package/src/payment/error.tsx +29 -0
  155. package/src/payment/footer.tsx +12 -0
  156. package/src/payment/form/addon.tsx +24 -0
  157. package/src/payment/form/address.tsx +119 -0
  158. package/src/payment/form/index.tsx +401 -0
  159. package/src/payment/form/phone.tsx +103 -0
  160. package/src/payment/form/stripe.tsx +195 -0
  161. package/src/payment/header.tsx +40 -0
  162. package/src/payment/index.tsx +367 -0
  163. package/src/payment/product-card.tsx +55 -0
  164. package/src/payment/product-item.tsx +121 -0
  165. package/src/payment/product-skeleton.tsx +39 -0
  166. package/src/payment/skeleton/overview.tsx +21 -0
  167. package/src/payment/skeleton/payment.tsx +35 -0
  168. package/src/payment/success.tsx +186 -0
  169. package/src/payment/summary.tsx +198 -0
  170. package/src/theme.ts +18 -0
  171. package/src/types/index.ts +29 -0
  172. package/src/types/shims.d.ts +18 -0
  173. package/src/util.ts +543 -0
package/es/util.js ADDED
@@ -0,0 +1,390 @@
1
+ import { BN, fromUnitToToken } from "@ocap/util";
2
+ import { defaultCountries } from "react-international-phone";
3
+ import dayjs from "./dayjs.js";
4
+ import { t } from "./locales/index.js";
5
+ export const PAYMENT_KIT_DID = "z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk";
6
+ export const getPrefix = () => {
7
+ const componentId = (window.blocklet.componentId || "").split("/").pop();
8
+ if (componentId === PAYMENT_KIT_DID) {
9
+ return window.blocklet.prefix;
10
+ }
11
+ const component = (window.blocklet.componentMountPoints || []).find((x) => x.did === PAYMENT_KIT_DID);
12
+ if (component) {
13
+ return component.mountPoint;
14
+ }
15
+ return window.blocklet.prefix;
16
+ };
17
+ export function formatToDate(date, locale = "en") {
18
+ if (!date) {
19
+ return "-";
20
+ }
21
+ return dayjs(date).locale(formatLocale(locale)).format("YYYY-MM-DD HH:mm:ss");
22
+ }
23
+ export function formatToDatetime(date, locale = "en") {
24
+ if (!date) {
25
+ return "-";
26
+ }
27
+ return dayjs(date).locale(formatLocale(locale)).format("lll");
28
+ }
29
+ export function formatTime(date, format = "YYYY-MM-DD HH:mm:ss", locale = "en") {
30
+ if (!date) {
31
+ return "-";
32
+ }
33
+ return dayjs(date).locale(formatLocale(locale)).format(format);
34
+ }
35
+ export function formatDateTime(date, locale = "en") {
36
+ return dayjs(date).locale(formatLocale(locale)).format("YYYY-MM-DD HH:mm");
37
+ }
38
+ export const formatLocale = (locale = "en") => {
39
+ if (locale === "tw") {
40
+ return "zh";
41
+ }
42
+ return locale;
43
+ };
44
+ export const formatPrettyMsLocale = (locale) => locale === "zh" ? "zh_CN" : "en_US";
45
+ export const formatError = (err) => {
46
+ const { details, errors, response } = err;
47
+ if (Array.isArray(errors)) {
48
+ return errors.map((x) => x.message).join("\n");
49
+ }
50
+ if (Array.isArray(details)) {
51
+ const formatted = details.map((e) => {
52
+ const errorMessage = e.message.replace(/["]/g, "'");
53
+ const errorPath = e.path.join(".");
54
+ return `${errorPath}: ${errorMessage}`;
55
+ });
56
+ return `Validate failed: ${formatted.join(";")}`;
57
+ }
58
+ if (response) {
59
+ return response.data.error || `${err.message}: ${JSON.stringify(response.data)}`;
60
+ }
61
+ return err.message;
62
+ };
63
+ export const formatPrice = (price, currency, unit_label, quantity = 1, bn = true, locale = "en") => {
64
+ const unit = getPriceUintAmountByCurrency(price, currency);
65
+ const amount = bn ? fromUnitToToken(new BN(unit).mul(new BN(quantity)), currency.decimal).toString() : +unit * quantity;
66
+ if (price?.type === "recurring" && price.recurring) {
67
+ const recurring = formatRecurring(price.recurring, false, "slash", locale);
68
+ if (unit_label) {
69
+ return `${amount} ${currency.symbol} / ${unit_label} ${recurring}`;
70
+ }
71
+ if (price.recurring.usage_type === "metered") {
72
+ return `${amount} ${currency.symbol} / unit ${recurring}`;
73
+ }
74
+ return `${amount} ${currency.symbol} ${recurring}`;
75
+ }
76
+ return `${amount} ${currency.symbol}`;
77
+ };
78
+ export const formatPriceAmount = (price, currency, unit_label, quantity = 1, bn = true) => {
79
+ const unit = getPriceUintAmountByCurrency(price, currency);
80
+ const amount = bn ? fromUnitToToken(new BN(unit).mul(new BN(quantity)), currency.decimal).toString() : +unit * quantity;
81
+ if (price?.type === "recurring" && price.recurring) {
82
+ if (unit_label) {
83
+ return `${amount} ${currency.symbol} / ${unit_label}`;
84
+ }
85
+ if (price.recurring.usage_type === "metered") {
86
+ return `${amount} ${currency.symbol} / unit`;
87
+ }
88
+ return `${amount} ${currency.symbol}`;
89
+ }
90
+ return `${amount} ${currency.symbol}`;
91
+ };
92
+ export function getStatementDescriptor(items) {
93
+ for (const item of items) {
94
+ if (item.price?.product?.statement_descriptor) {
95
+ return item.price?.product?.statement_descriptor;
96
+ }
97
+ }
98
+ return window.blocklet.appName;
99
+ }
100
+ export function formatRecurring(recurring, translate = true, separator = "per", locale = "en") {
101
+ const intervals = {
102
+ hour: "hourly",
103
+ day: "daily",
104
+ week: "weekly",
105
+ month: "monthly",
106
+ year: "yearly"
107
+ };
108
+ if (+recurring.interval_count === 1) {
109
+ const interval = t(`common.${recurring.interval}`, locale);
110
+ return translate ? t(`common.${intervals[recurring.interval]}`, locale) : separator ? t(`common.${separator}`, locale, { interval }) : interval;
111
+ }
112
+ return t("common.recurring", locale, {
113
+ count: recurring.interval_count,
114
+ interval: t(`common.${recurring.interval}s`, locale)
115
+ });
116
+ }
117
+ export function getPriceUintAmountByCurrency(price, currency) {
118
+ const options = getPriceCurrencyOptions(price);
119
+ const option = options.find((x) => x.currency_id === currency.id);
120
+ if (option) {
121
+ return option.unit_amount;
122
+ }
123
+ return price.unit_amount;
124
+ }
125
+ export function getPriceCurrencyOptions(price) {
126
+ if (Array.isArray(price.currency_options)) {
127
+ return price.currency_options;
128
+ }
129
+ return [{ currency_id: price.currency_id, unit_amount: price.unit_amount, tiers: null, custom_unit_amount: null }];
130
+ }
131
+ export function formatLineItemPricing(item, currency, trial, locale = "en") {
132
+ const price = item.upsell_price || item.price;
133
+ let quantity = t("common.qty", locale, { count: item.quantity });
134
+ if (price.recurring?.usage_type === "metered" || +item.quantity === 1) {
135
+ quantity = "";
136
+ }
137
+ const total = `${fromUnitToToken(
138
+ new BN(getPriceUintAmountByCurrency(price, currency)).mul(new BN(item.quantity)),
139
+ currency.decimal
140
+ )} ${currency.symbol}`;
141
+ const unit = `${fromUnitToToken(getPriceUintAmountByCurrency(price, currency))} ${currency.symbol}`;
142
+ const appendUnit = (v, alt) => {
143
+ if (price.product.unit_label) {
144
+ return `${v}/${price.product.unit_label}`;
145
+ }
146
+ if (price.recurring?.usage_type === "metered" || item.quantity === 1) {
147
+ return alt;
148
+ }
149
+ return quantity ? t("common.each", locale, { unit }) : "";
150
+ };
151
+ if (price.type === "recurring" && price.recurring) {
152
+ if (trial > 0) {
153
+ return {
154
+ primary: t("common.trial", locale, { count: trial }),
155
+ secondary: `${appendUnit(total, total)} ${formatRecurring(price.recurring, false, "slash", locale)}`,
156
+ quantity
157
+ };
158
+ }
159
+ return {
160
+ primary: total,
161
+ secondary: appendUnit(total, ""),
162
+ quantity
163
+ };
164
+ }
165
+ return {
166
+ primary: total,
167
+ secondary: appendUnit(total, ""),
168
+ quantity
169
+ };
170
+ }
171
+ export function getCheckoutAmount(items, currency, includeFreeTrial = false, upsell = true) {
172
+ let renew = new BN(0);
173
+ const total = items.reduce((acc, x) => {
174
+ const price = upsell ? x.upsell_price || x.price : x.price;
175
+ if (price.type === "recurring") {
176
+ renew = renew.add(new BN(getPriceUintAmountByCurrency(price, currency)).mul(new BN(x.quantity)));
177
+ if (includeFreeTrial) {
178
+ return acc;
179
+ }
180
+ if (price.recurring?.usage_type === "metered") {
181
+ return acc;
182
+ }
183
+ }
184
+ return acc.add(new BN(getPriceUintAmountByCurrency(price, currency)).mul(new BN(x.quantity)));
185
+ }, new BN(0)).toString();
186
+ return { subtotal: total, total, renew: renew.toString(), discount: "0", shipping: "0", tax: "0" };
187
+ }
188
+ export function getRecurringPeriod(recurring) {
189
+ const { interval } = recurring;
190
+ const count = +recurring.interval_count || 1;
191
+ const dayInMs = 24 * 60 * 60 * 1e3;
192
+ switch (interval) {
193
+ case "hour":
194
+ return 60 * 60 * 1e3;
195
+ case "day":
196
+ return count * dayInMs;
197
+ case "week":
198
+ return count * 7 * dayInMs;
199
+ case "month":
200
+ return count * 30 * dayInMs;
201
+ case "year":
202
+ return count * 365 * dayInMs;
203
+ default:
204
+ throw new Error(`Unsupported recurring interval: ${interval}`);
205
+ }
206
+ }
207
+ export function formatUpsellSaving(session, currency) {
208
+ const items = session.line_items;
209
+ if (items[0]?.upsell_price_id) {
210
+ return "0";
211
+ }
212
+ if (!items[0]?.price.upsell?.upsells_to) {
213
+ return "0";
214
+ }
215
+ const from = getCheckoutAmount(items, currency, false, false);
216
+ const to = getCheckoutAmount(
217
+ items.map((x) => ({
218
+ ...x,
219
+ upsell_price_id: x.price.upsell?.upsells_to_id,
220
+ upsell_price: x.price.upsell?.upsells_to
221
+ })),
222
+ currency,
223
+ false,
224
+ true
225
+ );
226
+ const fromRecurring = items[0].price?.recurring;
227
+ const toRecurring = items[0].price?.upsell?.upsells_to?.recurring;
228
+ if (!fromRecurring || !toRecurring) {
229
+ return "0";
230
+ }
231
+ const factor = Math.floor(getRecurringPeriod(toRecurring) / getRecurringPeriod(fromRecurring));
232
+ const before = new BN(from.total).mul(new BN(factor));
233
+ const after = new BN(to.total);
234
+ return Number(before.sub(after).mul(new BN(100)).div(before).toString()).toFixed(0);
235
+ }
236
+ export function formatCheckoutHeadlines(session, currency, locale = "en") {
237
+ const items = session.line_items;
238
+ const trial = session.subscription_data?.trial_period_days || 0;
239
+ const brand = getStatementDescriptor(items);
240
+ const { total } = getCheckoutAmount(items, currency, !!trial);
241
+ const amount = `${fromUnitToToken(total, currency.decimal)} ${currency.symbol}`;
242
+ if (items.length === 0) {
243
+ return {
244
+ action: t("payment.checkout.empty", locale),
245
+ amount: "0",
246
+ then: ""
247
+ };
248
+ }
249
+ const { name } = items[0]?.price.product || { name: "" };
250
+ if (items.every((x) => x.price.type === "one_time")) {
251
+ const action = t("payment.checkout.pay", locale, { payee: brand });
252
+ if (items.length > 1) {
253
+ return { action, amount };
254
+ }
255
+ return { action, amount, then: "" };
256
+ }
257
+ const item = items.find((x) => x.price.type === "recurring");
258
+ const recurring = formatRecurring(
259
+ (item?.upsell_price || item?.price)?.recurring,
260
+ false,
261
+ "per",
262
+ locale
263
+ );
264
+ if (items.every((x) => x.price.type === "recurring")) {
265
+ const hasMetered = items.some((x) => x.price.type === "recurring" && x.price.recurring?.usage_type === "metered");
266
+ const subscription2 = [
267
+ hasMetered ? t("payment.checkout.least", locale) : "",
268
+ fromUnitToToken(
269
+ items.reduce((acc, x) => {
270
+ if (x.price.recurring?.usage_type === "metered") {
271
+ return acc;
272
+ }
273
+ return acc.add(new BN(getPriceUintAmountByCurrency(x.price, currency)).mul(new BN(x.quantity)));
274
+ }, new BN(0)),
275
+ currency.decimal
276
+ ),
277
+ currency.symbol
278
+ ].filter(Boolean).join(" ");
279
+ if (items.length > 1) {
280
+ if (trial > 0) {
281
+ return {
282
+ action: t("payment.checkout.try2", locale, { name, count: items.length - 1 }),
283
+ amount: t("payment.checkout.free", locale, { count: trial }),
284
+ then: t("payment.checkout.then", locale, { subscription: subscription2, recurring })
285
+ };
286
+ }
287
+ return {
288
+ action: t("payment.checkout.sub2", locale, { name, count: items.length - 1 }),
289
+ amount,
290
+ then: recurring
291
+ };
292
+ }
293
+ if (trial > 0) {
294
+ return {
295
+ action: t("payment.checkout.try1", locale, { name }),
296
+ amount: t("payment.checkout.free", locale, { count: trial }),
297
+ then: t("payment.checkout.then", locale, { subscription: subscription2, recurring })
298
+ };
299
+ }
300
+ return {
301
+ action: t("payment.checkout.sub1", locale, { name }),
302
+ amount,
303
+ then: recurring
304
+ };
305
+ }
306
+ const subscription = fromUnitToToken(
307
+ items.filter((x) => x.price.type === "recurring").reduce((acc, x) => {
308
+ if (x.price.recurring?.usage_type === "metered") {
309
+ return acc;
310
+ }
311
+ return acc.add(new BN(getPriceUintAmountByCurrency(x.price, currency)).mul(new BN(x.quantity)));
312
+ }, new BN(0)),
313
+ currency.decimal
314
+ );
315
+ return {
316
+ action: t("payment.checkout.pay", locale, { payee: brand }),
317
+ amount,
318
+ then: t("payment.checkout.then", locale, { subscription: `${subscription} ${currency.symbol}`, recurring })
319
+ };
320
+ }
321
+ export function formatAmount(amount, decimals) {
322
+ return fromUnitToToken(amount, decimals);
323
+ }
324
+ export function findCurrency(methods, currencyId) {
325
+ for (const method of methods) {
326
+ for (const currency of method.payment_currencies) {
327
+ if (currency.id === currencyId) {
328
+ return currency;
329
+ }
330
+ }
331
+ }
332
+ return null;
333
+ }
334
+ export function isValidCountry(code) {
335
+ return defaultCountries.some((x) => x[1] === code);
336
+ }
337
+ export function stopEvent(e) {
338
+ try {
339
+ e.stopPropagation();
340
+ e.preventDefault();
341
+ } catch {
342
+ }
343
+ }
344
+ export function sleep(ms) {
345
+ return new Promise((resolve) => {
346
+ setTimeout(resolve, ms);
347
+ });
348
+ }
349
+ export const getSubscriptionTimeSummary = (subscription) => {
350
+ const lines = [`Started on ${formatToDate(subscription.start_date * 1e3)}`];
351
+ if (subscription.status === "active" || subscription.status === "trialing") {
352
+ if (subscription.cancel_at) {
353
+ lines.push(`will cancel on ${formatToDate(subscription.cancel_at * 1e3)}`);
354
+ } else if (subscription.cancel_at_period_end) {
355
+ lines.push(`will cancel on ${formatToDate(subscription.current_period_end * 1e3)}`);
356
+ } else {
357
+ lines.push(`will renew on ${formatToDate(subscription.current_period_end * 1e3)}`);
358
+ }
359
+ } else if (subscription.status === "past_due") {
360
+ lines.push(`will cancel on ${formatToDate(subscription.current_period_end * 1e3)}`);
361
+ } else if (subscription.status === "canceled") {
362
+ lines.push(`canceled on ${formatToDate(subscription.canceled_at * 1e3)}`);
363
+ }
364
+ return lines.join(", ");
365
+ };
366
+ export const getSubscriptionAction = (subscription) => {
367
+ if (subscription.status !== "canceled" && subscription.cancel_at_period_end) {
368
+ return { action: "recover", variant: "contained", color: "primary" };
369
+ }
370
+ if (subscription.status === "active" || subscription.status === "trialing") {
371
+ if (subscription.cancel_at) {
372
+ return null;
373
+ }
374
+ if (subscription.cancel_at_period_end) {
375
+ return { action: "recover", variant: "contained", color: "primary" };
376
+ }
377
+ return { action: "cancel", variant: "outlined", color: "inherit" };
378
+ }
379
+ if (subscription.status === "past_due") {
380
+ return { action: "pastDue", variant: "contained", color: "primary" };
381
+ }
382
+ return null;
383
+ };
384
+ export const mergeExtraParams = (extra = {}) => {
385
+ const params = new URLSearchParams(window.location.search);
386
+ Object.keys(extra).forEach((key) => {
387
+ params.set(key, extra[key]);
388
+ });
389
+ return params.toString();
390
+ };
package/lib/api.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ declare const api: import("axios").AxiosInstance;
2
+ export default api;
package/lib/api.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ var _context = require("@arcblock/ux/lib/Locale/context");
8
+ var _axios = _interopRequireDefault(require("axios"));
9
+ var _isNull = _interopRequireDefault(require("lodash/isNull"));
10
+ var _util = require("./util");
11
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
+ const api = _axios.default.create();
13
+ api.interceptors.request.use(config => {
14
+ const prefix = (0, _util.getPrefix)();
15
+ config.baseURL = prefix || "";
16
+ config.timeout = 8e3;
17
+ const livemode = localStorage.getItem("livemode");
18
+ const locale = (0, _context.getLocale)(window.blocklet.languages);
19
+ config.params = {
20
+ ...(config.params || {}),
21
+ livemode: (0, _isNull.default)(livemode) ? true : JSON.parse(livemode),
22
+ locale
23
+ };
24
+ return config;
25
+ }, err => Promise.reject(err));
26
+ module.exports = api;
@@ -0,0 +1,15 @@
1
+ /// <reference types="react" />
2
+ import { CheckoutProps } from '../types';
3
+ declare function Checkout({ id, onPaid, onError, mode, extraParams }: CheckoutProps): import("react").JSX.Element;
4
+ declare namespace Checkout {
5
+ var defaultProps: {
6
+ onPaid: any;
7
+ onError: {
8
+ (...data: any[]): void;
9
+ (message?: any, ...optionalParams: any[]): void;
10
+ };
11
+ mode: string;
12
+ extraParams: {};
13
+ };
14
+ }
15
+ export default Checkout;
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ module.exports = Checkout;
7
+ var _jsxRuntime = require("react/jsx-runtime");
8
+ var _ahooks = require("ahooks");
9
+ var _noop = _interopRequireDefault(require("lodash/noop"));
10
+ var _react = require("react");
11
+ var _ufo = require("ufo");
12
+ var _api = _interopRequireDefault(require("../api"));
13
+ var _payment = _interopRequireDefault(require("../payment"));
14
+ var _util = require("../util");
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
+ const startFromPaymentLink = async (id, params) => {
17
+ const {
18
+ data
19
+ } = await _api.default.post(`/api/checkout-sessions/start/${id}?${(0, _util.mergeExtraParams)(params)}`);
20
+ return data;
21
+ };
22
+ const fetchCheckoutSession = async id => {
23
+ const {
24
+ data
25
+ } = await _api.default.get(`/api/checkout-sessions/retrieve/${id}`);
26
+ return data;
27
+ };
28
+ function Checkout({
29
+ id,
30
+ onPaid,
31
+ onError,
32
+ mode,
33
+ extraParams
34
+ }) {
35
+ if (!id.startsWith("plink_") && !id.startsWith("cs_")) {
36
+ throw new Error("Either a checkout session or a payment link id is required.");
37
+ }
38
+ const type = id.startsWith("plink_") ? "paymentLink" : "checkoutSession";
39
+ const [state, setState] = (0, _ahooks.useSetState)({
40
+ completed: false,
41
+ appError: null
42
+ });
43
+ const {
44
+ error: apiError,
45
+ data
46
+ } = (0, _ahooks.useRequest)(() => type === "paymentLink" ? startFromPaymentLink(id, extraParams) : fetchCheckoutSession(id));
47
+ (0, _react.useEffect)(() => {
48
+ if (type === "paymentLink" && mode === "standalone" && data) {
49
+ window.location.replace((0, _ufo.joinURL)((0, _util.getPrefix)(), `/checkout/pay/${data.checkoutSession.id}`));
50
+ }
51
+ }, [type, mode, data]);
52
+ const handlePaid = () => {
53
+ setState({
54
+ completed: true
55
+ });
56
+ onPaid?.(data);
57
+ };
58
+ const handleError = err => {
59
+ console.error(err);
60
+ setState({
61
+ appError: err
62
+ });
63
+ onError?.(err);
64
+ };
65
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_payment.default, {
66
+ checkoutSession: data?.checkoutSession,
67
+ paymentMethods: data?.paymentMethods,
68
+ paymentIntent: data?.paymentIntent,
69
+ paymentLink: data?.paymentLink,
70
+ customer: data?.customer,
71
+ completed: state.completed,
72
+ error: apiError || state.appError,
73
+ onPaid: handlePaid,
74
+ onError: handleError,
75
+ mode
76
+ });
77
+ }
78
+ Checkout.defaultProps = {
79
+ onPaid: _noop.default,
80
+ onError: console.error,
81
+ mode: "inline",
82
+ extraParams: {}
83
+ };
@@ -0,0 +1,23 @@
1
+ /// <reference types="react" />
2
+ import { TextFieldProps } from '@mui/material';
3
+ import { RegisterOptions } from 'react-hook-form';
4
+ type InputProps = TextFieldProps & {
5
+ name: string;
6
+ label?: string;
7
+ placeholder?: string;
8
+ errorPosition?: 'right' | 'bottom';
9
+ rules?: RegisterOptions;
10
+ };
11
+ export declare function FormInputError({ error }: {
12
+ error: string;
13
+ }): import("react").JSX.Element;
14
+ declare function FormInput({ name, label, placeholder, rules, errorPosition, ...rest }: InputProps): import("react").JSX.Element;
15
+ declare namespace FormInput {
16
+ var defaultProps: {
17
+ label: string;
18
+ placeholder: string;
19
+ errorPosition: string;
20
+ rules: {};
21
+ };
22
+ }
23
+ export default FormInput;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.FormInputError = FormInputError;
7
+ module.exports = FormInput;
8
+ var _jsxRuntime = require("react/jsx-runtime");
9
+ var _material = require("@mui/material");
10
+ var _get = _interopRequireDefault(require("lodash/get"));
11
+ var _reactHookForm = require("react-hook-form");
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+ FormInput.defaultProps = {
14
+ label: "",
15
+ placeholder: "",
16
+ errorPosition: "bottom",
17
+ rules: {}
18
+ };
19
+ function FormInputError({
20
+ error
21
+ }) {
22
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.InputAdornment, {
23
+ position: "end",
24
+ children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
25
+ component: "span",
26
+ color: "error",
27
+ children: error
28
+ })
29
+ });
30
+ }
31
+ function FormInput({
32
+ name,
33
+ label,
34
+ placeholder,
35
+ rules,
36
+ errorPosition,
37
+ ...rest
38
+ }) {
39
+ const {
40
+ control,
41
+ formState
42
+ } = (0, _reactHookForm.useFormContext)();
43
+ const error = (0, _get.default)(formState.errors, name)?.message;
44
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_reactHookForm.Controller, {
45
+ name,
46
+ control,
47
+ rules,
48
+ render: ({
49
+ field
50
+ }) => /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
51
+ sx: {
52
+ width: "100%"
53
+ },
54
+ children: [!!label && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.FormLabel, {
55
+ children: label
56
+ }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.TextField, {
57
+ fullWidth: true,
58
+ error: !!(0, _get.default)(formState.errors, name),
59
+ helperText: errorPosition === "bottom" && error ? error : "",
60
+ placeholder,
61
+ size: "small",
62
+ ...field,
63
+ ...rest,
64
+ InputProps: Object.assign(rest.InputProps || {}, errorPosition === "right" && error ? {
65
+ endAdornment: /* @__PURE__ */(0, _jsxRuntime.jsx)(FormInputError, {
66
+ error
67
+ })
68
+ } : {})
69
+ })]
70
+ })
71
+ });
72
+ }
@@ -0,0 +1,2 @@
1
+ /// <reference types="react" />
2
+ export default function Livemode(): import("react").JSX.Element;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ module.exports = Livemode;
7
+ var _jsxRuntime = require("react/jsx-runtime");
8
+ var _context = require("@arcblock/ux/lib/Locale/context");
9
+ var _material = require("@mui/material");
10
+ function Livemode() {
11
+ const {
12
+ t
13
+ } = (0, _context.useLocaleContext)();
14
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Chip, {
15
+ label: t("common.livemode"),
16
+ size: "small",
17
+ sx: {
18
+ ml: 2,
19
+ height: 18,
20
+ lineHeight: 1,
21
+ textTransform: "uppercase",
22
+ fontSize: "0.8rem",
23
+ fontWeight: "bold",
24
+ borderRadius: "4px",
25
+ backgroundColor: "#ffde92",
26
+ color: "#bb5504"
27
+ }
28
+ });
29
+ }
@@ -0,0 +1,18 @@
1
+ /// <reference types="react" />
2
+ import type { TPricingTableExpanded } from '@blocklet/payment-types';
3
+ type Props = {
4
+ table: TPricingTableExpanded;
5
+ onSelect: (priceId: string) => void;
6
+ alignItems?: 'center' | 'left';
7
+ mode?: 'checkout' | 'select';
8
+ interval?: string;
9
+ };
10
+ declare function PricingTable({ table, alignItems, interval, mode, onSelect }: Props): import("react").JSX.Element;
11
+ declare namespace PricingTable {
12
+ var defaultProps: {
13
+ alignItems: string;
14
+ mode: string;
15
+ interval: string;
16
+ };
17
+ }
18
+ export default PricingTable;