@usethrottle/auth 0.6.1 → 0.8.0
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/dist/index.d.cts +20 -0
- package/dist/index.d.ts +20 -0
- package/dist/react/components/index.cjs +64 -14
- package/dist/react/components/index.cjs.map +1 -1
- package/dist/react/components/index.d.cts +7 -1
- package/dist/react/components/index.d.ts +7 -1
- package/dist/react/components/index.js +64 -14
- package/dist/react/components/index.js.map +1 -1
- package/dist/react/index.d.cts +20 -0
- package/dist/react/index.d.ts +20 -0
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -96,7 +96,10 @@ interface Order {
|
|
|
96
96
|
billingAddress: unknown | null;
|
|
97
97
|
shippingAddress: unknown | null;
|
|
98
98
|
discountCode: string | null;
|
|
99
|
+
/** Set only when the order is linked to exactly one subscription. Read `subscriptionIds`. */
|
|
99
100
|
subscriptionId: string | null;
|
|
101
|
+
/** Every subscription this order created, in line order. One cart can hold several. */
|
|
102
|
+
subscriptionIds: string[];
|
|
100
103
|
/**
|
|
101
104
|
* The invoice raised for this order, when one exists. Resolved on the
|
|
102
105
|
* detail read only — the list would need a lookup per row.
|
|
@@ -120,6 +123,8 @@ interface OrderLineItem {
|
|
|
120
123
|
discountAmount: number;
|
|
121
124
|
total: number;
|
|
122
125
|
imageUrl: string | null;
|
|
126
|
+
/** The subscription this line created, or null for a one-time line. */
|
|
127
|
+
subscriptionId: string | null;
|
|
123
128
|
}
|
|
124
129
|
/**
|
|
125
130
|
* What `getOrder` returns. Deliberately NOT folded into `Order`: the list route
|
|
@@ -175,6 +180,21 @@ interface Subscription {
|
|
|
175
180
|
totalPayments: number | null;
|
|
176
181
|
paymentsMade: number;
|
|
177
182
|
completedAt: string | null;
|
|
183
|
+
/** Installment plans only: every payment in order; dueAt is an estimate. */
|
|
184
|
+
paymentSchedule?: Array<{
|
|
185
|
+
index: number;
|
|
186
|
+
amount: number;
|
|
187
|
+
discount: number;
|
|
188
|
+
net: number;
|
|
189
|
+
intervalUnit: string | null;
|
|
190
|
+
intervalCount: number | null;
|
|
191
|
+
status: 'paid' | 'due' | 'upcoming';
|
|
192
|
+
dueAt: string | null;
|
|
193
|
+
}> | null;
|
|
194
|
+
/** Installment plans only: the sum of every payment's net amount. */
|
|
195
|
+
scheduleTotal?: number | null;
|
|
196
|
+
/** Installment plans only: what the next payment will charge; null once complete. */
|
|
197
|
+
nextPaymentAmount?: number | null;
|
|
178
198
|
amount: number;
|
|
179
199
|
quantity: number;
|
|
180
200
|
currency: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -96,7 +96,10 @@ interface Order {
|
|
|
96
96
|
billingAddress: unknown | null;
|
|
97
97
|
shippingAddress: unknown | null;
|
|
98
98
|
discountCode: string | null;
|
|
99
|
+
/** Set only when the order is linked to exactly one subscription. Read `subscriptionIds`. */
|
|
99
100
|
subscriptionId: string | null;
|
|
101
|
+
/** Every subscription this order created, in line order. One cart can hold several. */
|
|
102
|
+
subscriptionIds: string[];
|
|
100
103
|
/**
|
|
101
104
|
* The invoice raised for this order, when one exists. Resolved on the
|
|
102
105
|
* detail read only — the list would need a lookup per row.
|
|
@@ -120,6 +123,8 @@ interface OrderLineItem {
|
|
|
120
123
|
discountAmount: number;
|
|
121
124
|
total: number;
|
|
122
125
|
imageUrl: string | null;
|
|
126
|
+
/** The subscription this line created, or null for a one-time line. */
|
|
127
|
+
subscriptionId: string | null;
|
|
123
128
|
}
|
|
124
129
|
/**
|
|
125
130
|
* What `getOrder` returns. Deliberately NOT folded into `Order`: the list route
|
|
@@ -175,6 +180,21 @@ interface Subscription {
|
|
|
175
180
|
totalPayments: number | null;
|
|
176
181
|
paymentsMade: number;
|
|
177
182
|
completedAt: string | null;
|
|
183
|
+
/** Installment plans only: every payment in order; dueAt is an estimate. */
|
|
184
|
+
paymentSchedule?: Array<{
|
|
185
|
+
index: number;
|
|
186
|
+
amount: number;
|
|
187
|
+
discount: number;
|
|
188
|
+
net: number;
|
|
189
|
+
intervalUnit: string | null;
|
|
190
|
+
intervalCount: number | null;
|
|
191
|
+
status: 'paid' | 'due' | 'upcoming';
|
|
192
|
+
dueAt: string | null;
|
|
193
|
+
}> | null;
|
|
194
|
+
/** Installment plans only: the sum of every payment's net amount. */
|
|
195
|
+
scheduleTotal?: number | null;
|
|
196
|
+
/** Installment plans only: what the next payment will charge; null once complete. */
|
|
197
|
+
nextPaymentAmount?: number | null;
|
|
178
198
|
amount: number;
|
|
179
199
|
quantity: number;
|
|
180
200
|
currency: string;
|
|
@@ -780,6 +780,7 @@ var THROTTLE_ELEMENT_KEYS = [
|
|
|
780
780
|
"orderDetail.cancelButton",
|
|
781
781
|
"orderDetail.returnButton",
|
|
782
782
|
"orderDetail.invoiceButton",
|
|
783
|
+
"orderDetail.subscriptionButton",
|
|
783
784
|
"orderDetail.actions",
|
|
784
785
|
"invoiceDetail.layout",
|
|
785
786
|
"invoiceDetail.main",
|
|
@@ -1187,7 +1188,8 @@ var enUS = {
|
|
|
1187
1188
|
quantity: "Qty",
|
|
1188
1189
|
shippingAddress: "Shipping address",
|
|
1189
1190
|
billingAddress: "Billing address",
|
|
1190
|
-
viewSubscription: "View subscription"
|
|
1191
|
+
viewSubscription: "View subscription",
|
|
1192
|
+
viewSubscriptionFor: "View subscription for"
|
|
1191
1193
|
},
|
|
1192
1194
|
invoices: {
|
|
1193
1195
|
empty: "No invoices yet",
|
|
@@ -1226,6 +1228,11 @@ var enUS = {
|
|
|
1226
1228
|
cancelledOn: "Cancelled on",
|
|
1227
1229
|
trialEnds: "Trial ends",
|
|
1228
1230
|
installmentProgress: "Payment {paid} of {total}",
|
|
1231
|
+
installmentTotal: "{amount} total",
|
|
1232
|
+
installmentNext: "Next {amount} on {date}",
|
|
1233
|
+
/** Spec §5: a varied schedule's dated list; dates are estimates, hence "~". */
|
|
1234
|
+
upcomingPayments: "Upcoming payments",
|
|
1235
|
+
upcomingPayment: "{amount} \xB7 ~{date}",
|
|
1229
1236
|
cancelButton: "Cancel",
|
|
1230
1237
|
cancelAtPeriodEnd: "Cancel at period end",
|
|
1231
1238
|
cancelNow: "Cancel immediately",
|
|
@@ -3862,6 +3869,16 @@ function OrderTimeline(props) {
|
|
|
3862
3869
|
] });
|
|
3863
3870
|
}
|
|
3864
3871
|
|
|
3872
|
+
// src/react/components/account/order-subscription-links.ts
|
|
3873
|
+
function orderSubscriptionLinks(order, labels) {
|
|
3874
|
+
const ids = order.subscriptionIds?.length ? order.subscriptionIds : order.subscriptionId ? [order.subscriptionId] : [];
|
|
3875
|
+
if (ids.length === 1) return [{ id: ids[0], label: labels.single }];
|
|
3876
|
+
return ids.map((id, index) => {
|
|
3877
|
+
const name = order.lineItems.find((li) => li.subscriptionId === id)?.name;
|
|
3878
|
+
return { id, label: name ? `${labels.named} ${name}` : `${labels.single} ${index + 1}` };
|
|
3879
|
+
});
|
|
3880
|
+
}
|
|
3881
|
+
|
|
3865
3882
|
// src/react/components/account/OrderDetail.tsx
|
|
3866
3883
|
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
3867
3884
|
var CAN_PAY = /* @__PURE__ */ new Set(["draft", "pending"]);
|
|
@@ -4022,14 +4039,19 @@ function OrderDetail(props) {
|
|
|
4022
4039
|
children: t.orders.reorder
|
|
4023
4040
|
}
|
|
4024
4041
|
) : null,
|
|
4025
|
-
|
|
4042
|
+
props.onViewSubscription ? orderSubscriptionLinks(order, {
|
|
4043
|
+
single: t.orders.viewSubscription,
|
|
4044
|
+
named: t.orders.viewSubscriptionFor
|
|
4045
|
+
}).map((link) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
4026
4046
|
Button,
|
|
4027
4047
|
{
|
|
4028
4048
|
variant: "secondary",
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4049
|
+
elementKey: "orderDetail.subscriptionButton",
|
|
4050
|
+
onClick: () => props.onViewSubscription(link.id),
|
|
4051
|
+
children: link.label
|
|
4052
|
+
},
|
|
4053
|
+
link.id
|
|
4054
|
+
)) : null,
|
|
4033
4055
|
showReturn ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
4034
4056
|
Button,
|
|
4035
4057
|
{
|
|
@@ -4397,6 +4419,18 @@ function isIntervalUnit(value) {
|
|
|
4397
4419
|
return typeof value === "string" && INTERVAL_UNITS.includes(value);
|
|
4398
4420
|
}
|
|
4399
4421
|
|
|
4422
|
+
// ../core-cadence/src/schedule.ts
|
|
4423
|
+
function isVariedSchedule(rows) {
|
|
4424
|
+
if (!rows || rows.length === 0) return false;
|
|
4425
|
+
return rows.some(
|
|
4426
|
+
(r, i) => r.discount !== 0 || r.amount !== rows[0].amount || i > 1 && (r.intervalUnit !== rows[1].intervalUnit || r.intervalCount !== rows[1].intervalCount)
|
|
4427
|
+
);
|
|
4428
|
+
}
|
|
4429
|
+
function upcomingSchedulePayments(rows) {
|
|
4430
|
+
if (!rows || !isVariedSchedule(rows)) return [];
|
|
4431
|
+
return rows.filter((r) => r.status !== "paid" && r.dueAt != null);
|
|
4432
|
+
}
|
|
4433
|
+
|
|
4400
4434
|
// ../core-cadence/src/labels.ts
|
|
4401
4435
|
var NAMED_NOUN = {
|
|
4402
4436
|
weekly: "week",
|
|
@@ -4412,6 +4446,10 @@ function cadenceNoun(cadence) {
|
|
|
4412
4446
|
}
|
|
4413
4447
|
return cadence.interval;
|
|
4414
4448
|
}
|
|
4449
|
+
function scheduleDeal(sub) {
|
|
4450
|
+
if (!sub.paymentSchedule || sub.scheduleTotal == null || !isVariedSchedule(sub.paymentSchedule)) return null;
|
|
4451
|
+
return { total: sub.scheduleTotal, payments: sub.paymentSchedule.length };
|
|
4452
|
+
}
|
|
4415
4453
|
|
|
4416
4454
|
// src/react/components/account/SubscriptionsPanel.tsx
|
|
4417
4455
|
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
@@ -4438,7 +4476,20 @@ function SubscriptionsPanel(props) {
|
|
|
4438
4476
|
await run(fn);
|
|
4439
4477
|
})();
|
|
4440
4478
|
};
|
|
4441
|
-
const priceLabel = (sub) =>
|
|
4479
|
+
const priceLabel = (sub) => {
|
|
4480
|
+
const deal = scheduleDeal(sub);
|
|
4481
|
+
return deal ? t.subscriptions.installmentTotal.replace("{amount}", formatMoney(deal.total, sub.currency, locale)) : `${formatMoney(sub.amount, sub.currency, locale)} / ${cadenceNoun(sub)}${sub.quantity > 1 ? ` \xD7 ${sub.quantity}` : ""}`;
|
|
4482
|
+
};
|
|
4483
|
+
const nextPaymentLabel = (sub) => {
|
|
4484
|
+
if (!isVariedSchedule(sub.paymentSchedule) || !sub.paymentSchedule || sub.nextPaymentAmount == null) return null;
|
|
4485
|
+
const upcoming = sub.paymentSchedule.find((r) => r.status !== "paid");
|
|
4486
|
+
return t.subscriptions.installmentNext.replace("{amount}", formatMoney(sub.nextPaymentAmount, sub.currency, locale)).replace("{date}", formatDate(upcoming?.dueAt ?? sub.currentPeriodEnd, locale));
|
|
4487
|
+
};
|
|
4488
|
+
const upcomingList = (sub) => {
|
|
4489
|
+
const upcoming = upcomingSchedulePayments(sub.paymentSchedule);
|
|
4490
|
+
if (upcoming.length === 0) return null;
|
|
4491
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ul", { className: "throttle-muted", "aria-label": t.subscriptions.upcomingPayments, children: upcoming.map((r) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("li", { children: t.subscriptions.upcomingPayment.replace("{amount}", formatMoney(r.net, sub.currency, locale)).replace("{date}", formatDate(r.dueAt, locale)) }, r.dueAt)) });
|
|
4492
|
+
};
|
|
4442
4493
|
const renewsLabel = (sub) => formatDate(
|
|
4443
4494
|
sub.status === "completed" ? sub.completedAt ?? sub.currentPeriodEnd : sub.status === "cancelled" ? sub.cancelledAt ?? sub.currentPeriodEnd : sub.currentPeriodEnd,
|
|
4444
4495
|
locale
|
|
@@ -4520,7 +4571,9 @@ function SubscriptionsPanel(props) {
|
|
|
4520
4571
|
columns: [
|
|
4521
4572
|
{ key: "plan", label: t.subscriptions.columnPlan, render: (sub) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
|
|
4522
4573
|
sub.planName ?? sub.planReference,
|
|
4523
|
-
sub.totalPayments != null ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "throttle-muted", children: t.subscriptions.installmentProgress.replace("{paid}", String(Math.min(sub.paymentsMade ?? 0, sub.totalPayments))).replace("{total}", String(sub.totalPayments)) }) : null
|
|
4574
|
+
sub.totalPayments != null ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "throttle-muted", children: t.subscriptions.installmentProgress.replace("{paid}", String(Math.min(sub.paymentsMade ?? 0, sub.totalPayments))).replace("{total}", String(sub.totalPayments)) }) : null,
|
|
4575
|
+
nextPaymentLabel(sub) ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "throttle-muted", children: nextPaymentLabel(sub) }) : null,
|
|
4576
|
+
upcomingList(sub)
|
|
4524
4577
|
] }) },
|
|
4525
4578
|
{ key: "price", label: t.subscriptions.columnPrice, render: (sub) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "throttle-table__money", children: priceLabel(sub) }) },
|
|
4526
4579
|
{ key: "renews", label: t.subscriptions.columnRenews, render: (sub) => renewsLabel(sub) },
|
|
@@ -4538,12 +4591,9 @@ function SubscriptionsPanel(props) {
|
|
|
4538
4591
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(StatusBadge, { status: sub.status, labels: t.subscriptions.statusLabels })
|
|
4539
4592
|
] }),
|
|
4540
4593
|
sub.totalPayments != null ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "throttle-muted", children: t.subscriptions.installmentProgress.replace("{paid}", String(Math.min(sub.paymentsMade ?? 0, sub.totalPayments))).replace("{total}", String(sub.totalPayments)) }) : null,
|
|
4541
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
cadenceNoun(sub),
|
|
4545
|
-
sub.quantity > 1 ? ` \xD7 ${sub.quantity}` : ""
|
|
4546
|
-
] }),
|
|
4594
|
+
nextPaymentLabel(sub) ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "throttle-muted", children: nextPaymentLabel(sub) }) : null,
|
|
4595
|
+
upcomingList(sub),
|
|
4596
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "throttle-muted", children: priceLabel(sub) }),
|
|
4547
4597
|
sub.status === "completed" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("p", { className: "throttle-muted", children: [
|
|
4548
4598
|
t.subscriptions.statusLabels.completed,
|
|
4549
4599
|
" ",
|