@mesub/react 0.1.0 → 0.1.2

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/README.md CHANGED
@@ -16,9 +16,22 @@ part in the browser: picking one, connecting it, signing in the right order.
16
16
 
17
17
  **[Read the docs](https://docs.mesub.io/docs/react)** for the walkthrough.
18
18
 
19
- > **Status: early, 0.x, not on npm yet.** The API may still change between
20
- > minor versions. See the [board](https://github.com/orgs/Mesub-io/projects/5)
21
- > for what is next.
19
+ [![npm](https://img.shields.io/npm/v/@mesub/react)](https://www.npmjs.com/package/@mesub/react)
20
+
21
+ > **Status: early, 0.x.** The API may still change between minor versions:
22
+ > `npm update` takes patches (0.1.x), a new minor (0.2.0) takes
23
+ > `npm install @mesub/react@latest`. See the
24
+ > [board](https://github.com/orgs/Mesub-io/projects/5) for what is next.
25
+
26
+ ## Install
27
+
28
+ ```sh
29
+ npm install @mesub/react
30
+ ```
31
+
32
+ `react` and `react-dom` 18 or later are peer dependencies. Every release is
33
+ built by GitHub Actions from a tagged commit and published with a provenance
34
+ statement: `npm audit signatures` verifies it.
22
35
 
23
36
  ## Requirements
24
37
 
@@ -57,7 +70,7 @@ export function App({ children }) {
57
70
  | Prop | What it is |
58
71
  | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
59
72
  | `endpoint` | Where you mounted the routes. A path on your site, or a full URL. |
60
- | `chain` | The network the wallet signs for: `solana:devnet` (the default) or `solana:mainnet`. It must match your plans' `network`. |
73
+ | `chain` | The network the wallet signs for: `solana:mainnet` (the default, where Mesub runs). It must match your plans' `network`. |
61
74
  | `fetch` | Your own `(url, init) => Promise<Response>`, to add headers or credentials. |
62
75
  | `theme` | `light`, `dark` or `auto`, set on the widget as `data-mesub-theme`. |
63
76
  | `manageUrl` | Where "Cancel any time" leads once subscribed: your own page (`/account`, or a full URL). Mesub's page by default; `null` for no button. |
@@ -88,8 +101,10 @@ import { SubscribeButton } from '@mesub/react';
88
101
  dialog, from the plan to the receipt:
89
102
 
90
103
  1. **The plan**: its name, price and period, from `GET /plans/:slug`, and its end
91
- date when it has one. A plan that ends before a second charge can run is
92
- priced `once`, with the date its access runs to.
104
+ when it has one. A plan ends on any second, so its end is always written
105
+ with its time, in UTC, the same for every subscriber: `Oct 20, 2026, 23:59 UTC`.
106
+ A plan that ends before a second charge can run is priced `once`, with the
107
+ end its access runs to.
93
108
  2. **A wallet**: the installed wallets that can sign
94
109
  ([Wallet Standard](https://github.com/wallet-standard/wallet-standard), so
95
110
  Phantom, Solflare and the others). The one picked is asked for its account.
package/dist/index.cjs CHANGED
@@ -457,6 +457,14 @@ function moment(iso, now = Date.now()) {
457
457
  function shortMoment(iso, now = Date.now()) {
458
458
  return written(iso, { month: "short", day: "numeric" }, now);
459
459
  }
460
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
461
+ var two = (n) => String(n).padStart(2, "0");
462
+ function planEnd(iso) {
463
+ if (!iso) return null;
464
+ const date = new Date(iso);
465
+ if (Number.isNaN(date.getTime())) return null;
466
+ return `${MONTHS[date.getUTCMonth()]} ${date.getUTCDate()}, ${date.getUTCFullYear()}, ${two(date.getUTCHours())}:${two(date.getUTCMinutes())} UTC`;
467
+ }
460
468
  function shortAddress(address) {
461
469
  return `${address.slice(0, 4)}\u2026${address.slice(-4)}`;
462
470
  }
@@ -1426,7 +1434,7 @@ function planScreen(loaded, titleId, reload, close) {
1426
1434
  function stageScreen(props) {
1427
1435
  const { view, plan, chain, titleId } = props;
1428
1436
  const { text: price, title: exact } = briefPrice(plan);
1429
- const ends = moment(plan.ends_at);
1437
+ const ends = planEnd(plan.ends_at);
1430
1438
  const single = view.name === "review" ? singleCharge(plan, view.prepared.terms.message) : view.name === "signing" || view.name === "subscribed" ? view.single : singleCharge(plan);
1431
1439
  const every = single ? "once" : cadence(plan.period_hours);
1432
1440
  const merchant = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
@@ -1626,7 +1634,7 @@ function stageScreen(props) {
1626
1634
  };
1627
1635
  }
1628
1636
  const nextCharge = view.single ? null : moment(view.subscription.next_charge_at);
1629
- const accessUntil = view.single ? moment(view.subscription.access_until) ?? ends : null;
1637
+ const accessUntil = view.single ? ends ?? moment(view.subscription.access_until) : null;
1630
1638
  const manage = manageLink(props.manageUrl, view.cancelUrl);
1631
1639
  return {
1632
1640
  step: "subscribed",
@@ -1747,7 +1755,7 @@ function consequence(action, subscription, planEndsAt) {
1747
1755
  }
1748
1756
  if (action === "resume") {
1749
1757
  if (end && until && noChargeAt(Date.parse(end), planEndsAt)) {
1750
- return `It runs again until ${until}, when the plan ends. Nothing more is charged.`;
1758
+ return `It runs again until ${planEnd(planEndsAt)}, when the plan ends. Nothing more is charged.`;
1751
1759
  }
1752
1760
  return until ? `Charges start again on ${until}, as before.` : "Charges start again, as before.";
1753
1761
  }
@@ -2659,9 +2667,9 @@ function SubscriptionDialog({
2659
2667
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dt", { children: "Total paid" }),
2660
2668
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dd", { title: total.title, children: total.text })
2661
2669
  ] }) : null,
2662
- moment(plan?.ends_at) ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-mesub-row": "", children: [
2670
+ planEnd(plan?.ends_at) ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-mesub-row": "", children: [
2663
2671
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dt", { children: "Plan ends" }),
2664
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dd", { children: moment(plan?.ends_at) })
2672
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dd", { children: planEnd(plan?.ends_at) })
2665
2673
  ] }) : null,
2666
2674
  closeFrom(row) ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-mesub-row": "", children: [
2667
2675
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dt", { children: "Close from" }),
@@ -2776,7 +2784,7 @@ function SubscriptionDialog({
2776
2784
  var import_jsx_runtime8 = require("react/jsx-runtime");
2777
2785
  function MesubProvider({
2778
2786
  endpoint,
2779
- chain = "solana:devnet",
2787
+ chain = "solana:mainnet",
2780
2788
  fetch,
2781
2789
  theme,
2782
2790
  manageUrl,