@streamoid/settings 0.12.4 → 0.14.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.mts +164 -8
- package/dist/index.d.ts +164 -8
- package/dist/index.js +392 -69
- package/dist/index.mjs +390 -67
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -45,6 +45,7 @@ __export(index_exports, {
|
|
|
45
45
|
OrganizationModal: () => OrganizationModal,
|
|
46
46
|
OrganizationPicker: () => OrganizationPicker,
|
|
47
47
|
POOL_ERROR_CODES: () => POOL_ERROR_CODES,
|
|
48
|
+
POOL_EXPIRY_MAX_MONTHS: () => POOL_EXPIRY_MAX_MONTHS,
|
|
48
49
|
POOL_NOTE_MAX_LENGTH: () => POOL_NOTE_MAX_LENGTH,
|
|
49
50
|
PerUserLimitsView: () => PerUserLimitsView,
|
|
50
51
|
ProfileAvatar: () => ProfileAvatar,
|
|
@@ -84,23 +85,35 @@ __export(index_exports, {
|
|
|
84
85
|
describeAllowance: () => describeAllowance,
|
|
85
86
|
describeDefaultLimit: () => describeDefaultLimit,
|
|
86
87
|
describeMemberLimit: () => describeMemberLimit,
|
|
88
|
+
entitlementFromBody: () => entitlementFromBody,
|
|
89
|
+
entitlementFromFailure: () => entitlementFromFailure,
|
|
90
|
+
expiryChoiceFor: () => expiryChoiceFor,
|
|
87
91
|
findBillingError: () => findBillingError,
|
|
88
92
|
findPoolError: () => findPoolError,
|
|
89
93
|
formatCreditLimit: () => formatCreditLimit,
|
|
90
94
|
formatCredits: () => formatCredits,
|
|
95
|
+
formatPoolEndsAt: () => formatPoolEndsAt,
|
|
91
96
|
formatPoolSplit: () => formatPoolSplit,
|
|
92
97
|
groupWorkspaceList: () => groupWorkspaceList,
|
|
98
|
+
hasPaidFeatures: () => hasPaidFeatures,
|
|
93
99
|
isLimitBelowUsage: () => isLimitBelowUsage,
|
|
100
|
+
isPaidPlan: () => isPaidPlan,
|
|
101
|
+
isSponsoredEntitlement: () => isSponsoredEntitlement,
|
|
94
102
|
joinMembersWithLimits: () => joinMembersWithLimits,
|
|
95
103
|
lastUsedLabel: () => lastUsedLabel,
|
|
96
104
|
limitBelowUsageUsed: () => limitBelowUsageUsed,
|
|
97
105
|
limitSourceLabel: () => limitSourceLabel,
|
|
106
|
+
loadCurrentPlan: () => loadCurrentPlan,
|
|
98
107
|
loadWorkspaceOrganization: () => loadWorkspaceOrganization,
|
|
99
108
|
memberRoleUpdate: () => memberRoleUpdate,
|
|
109
|
+
minPoolEndDate: () => minPoolEndDate,
|
|
100
110
|
minimumCreditLimit: () => minimumCreditLimit,
|
|
101
111
|
ownCreditsFirstText: () => ownCreditsFirstText,
|
|
112
|
+
parseBillingEntitlement: () => parseBillingEntitlement,
|
|
102
113
|
pausedOwnCreditsText: () => pausedOwnCreditsText,
|
|
114
|
+
poolEndsAtFrom: () => poolEndsAtFrom,
|
|
103
115
|
poolErrorMessage: () => poolErrorMessage,
|
|
116
|
+
poolRenewsAtCycleEnd: () => poolRenewsAtCycleEnd,
|
|
104
117
|
poolWorkspaceName: () => poolWorkspaceName,
|
|
105
118
|
readSettingsCaller: () => readSettingsCaller,
|
|
106
119
|
rememberSettingsCaller: () => rememberSettingsCaller,
|
|
@@ -108,6 +121,10 @@ __export(index_exports, {
|
|
|
108
121
|
roundCredits: () => roundCredits,
|
|
109
122
|
settingsReturnTarget: () => settingsReturnTarget,
|
|
110
123
|
sharedPoolBannerText: () => sharedPoolBannerText,
|
|
124
|
+
sharedPoolEndsText: () => sharedPoolEndsText,
|
|
125
|
+
sponsoredCreditsText: () => sponsoredCreditsText,
|
|
126
|
+
toLocalDateInput: () => toLocalDateInput,
|
|
127
|
+
useBillingEntitlement: () => useBillingEntitlement,
|
|
111
128
|
useSettingsAdapters: () => useSettingsAdapters,
|
|
112
129
|
useWorkspaceInvitePermission: () => useWorkspaceInvitePermission,
|
|
113
130
|
useWorkspaceOrganization: () => useWorkspaceOrganization,
|
|
@@ -9655,6 +9672,76 @@ function describeAllowance(member) {
|
|
|
9655
9672
|
const allowance = `${credits(member.allowance)} this cycle`;
|
|
9656
9673
|
return member.mode === "percent" ? `${formatPoolSplit(member)} \xB7 ${allowance}` : allowance;
|
|
9657
9674
|
}
|
|
9675
|
+
var POOL_EXPIRY_MAX_MONTHS = 120;
|
|
9676
|
+
function addCalendarMonths(date, months) {
|
|
9677
|
+
const target = new Date(date.getFullYear(), date.getMonth() + months, 1);
|
|
9678
|
+
const lastDay = new Date(target.getFullYear(), target.getMonth() + 1, 0).getDate();
|
|
9679
|
+
return new Date(
|
|
9680
|
+
target.getFullYear(),
|
|
9681
|
+
target.getMonth(),
|
|
9682
|
+
Math.min(date.getDate(), lastDay),
|
|
9683
|
+
date.getHours(),
|
|
9684
|
+
date.getMinutes(),
|
|
9685
|
+
date.getSeconds(),
|
|
9686
|
+
date.getMilliseconds()
|
|
9687
|
+
);
|
|
9688
|
+
}
|
|
9689
|
+
var pad2 = (n) => String(n).padStart(2, "0");
|
|
9690
|
+
function toLocalDateInput(date) {
|
|
9691
|
+
return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`;
|
|
9692
|
+
}
|
|
9693
|
+
function minPoolEndDate(now = /* @__PURE__ */ new Date()) {
|
|
9694
|
+
return toLocalDateInput(new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1));
|
|
9695
|
+
}
|
|
9696
|
+
function parseLocalDate(value) {
|
|
9697
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value.trim());
|
|
9698
|
+
if (!match) return null;
|
|
9699
|
+
const [year, month, day] = [Number(match[1]), Number(match[2]) - 1, Number(match[3])];
|
|
9700
|
+
const date = new Date(year, month, day);
|
|
9701
|
+
return date.getFullYear() === year && date.getMonth() === month && date.getDate() === day ? date : null;
|
|
9702
|
+
}
|
|
9703
|
+
function poolEndsAtFrom(choice, now = /* @__PURE__ */ new Date()) {
|
|
9704
|
+
switch (choice.kind) {
|
|
9705
|
+
case "never":
|
|
9706
|
+
return { ok: true, value: null };
|
|
9707
|
+
case "month":
|
|
9708
|
+
return { ok: true, value: addCalendarMonths(now, 1).toISOString() };
|
|
9709
|
+
case "year":
|
|
9710
|
+
return { ok: true, value: addCalendarMonths(now, 12).toISOString() };
|
|
9711
|
+
case "months": {
|
|
9712
|
+
const { months } = choice;
|
|
9713
|
+
if (!Number.isInteger(months) || months < 1 || months > POOL_EXPIRY_MAX_MONTHS) {
|
|
9714
|
+
return { ok: false, reason: `Enter a whole number of months from 1 to ${POOL_EXPIRY_MAX_MONTHS}` };
|
|
9715
|
+
}
|
|
9716
|
+
return { ok: true, value: addCalendarMonths(now, months).toISOString() };
|
|
9717
|
+
}
|
|
9718
|
+
case "date": {
|
|
9719
|
+
if (!choice.date) return { ok: false, reason: "Choose a date" };
|
|
9720
|
+
const date = parseLocalDate(choice.date);
|
|
9721
|
+
if (!date) return { ok: false, reason: "Choose a valid date" };
|
|
9722
|
+
if (choice.date < minPoolEndDate(now)) return { ok: false, reason: "Choose a date after today" };
|
|
9723
|
+
return { ok: true, value: date.toISOString() };
|
|
9724
|
+
}
|
|
9725
|
+
}
|
|
9726
|
+
}
|
|
9727
|
+
function expiryChoiceFor(member) {
|
|
9728
|
+
const endsAt = member?.endsAt ? new Date(member.endsAt) : null;
|
|
9729
|
+
if (!endsAt || !Number.isFinite(endsAt.getTime())) return { kind: "never" };
|
|
9730
|
+
return { kind: "date", date: toLocalDateInput(endsAt) };
|
|
9731
|
+
}
|
|
9732
|
+
function formatPoolEndsAt(endsAt) {
|
|
9733
|
+
const date = endsAt ? new Date(endsAt) : null;
|
|
9734
|
+
if (!date || !Number.isFinite(date.getTime())) return "Never";
|
|
9735
|
+
return date.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
|
|
9736
|
+
}
|
|
9737
|
+
function sharedPoolEndsText(pool) {
|
|
9738
|
+
return pool.endsAt ? `Sharing ends on ${formatPoolEndsAt(pool.endsAt)}.` : "Sharing ends: Never.";
|
|
9739
|
+
}
|
|
9740
|
+
function poolRenewsAtCycleEnd(pool) {
|
|
9741
|
+
if (!pool.cycleEnd) return false;
|
|
9742
|
+
if (!pool.endsAt) return true;
|
|
9743
|
+
return new Date(pool.endsAt).getTime() > new Date(pool.cycleEnd).getTime();
|
|
9744
|
+
}
|
|
9658
9745
|
function poolWorkspaceName(name) {
|
|
9659
9746
|
return name?.trim() || "Unknown workspace";
|
|
9660
9747
|
}
|
|
@@ -9662,12 +9749,8 @@ function sharedPoolBannerText(pool) {
|
|
|
9662
9749
|
const sponsor = pool.sponsorName?.trim() || "another workspace";
|
|
9663
9750
|
return `Credits shared by ${sponsor}: ${formatCredits(pool.remaining)} of ${formatCredits(pool.allowance)} left this cycle`;
|
|
9664
9751
|
}
|
|
9665
|
-
function pausedOwnCreditsText(
|
|
9666
|
-
|
|
9667
|
-
if (typeof own !== "number" || !Number.isFinite(own)) {
|
|
9668
|
-
return "This workspace spends these shared credits, not its own; credits bought here can't be used while it does.";
|
|
9669
|
-
}
|
|
9670
|
-
return `This workspace's own ${credits(own)} ${own === 1 ? "is" : "are"} paused while it uses shared credits. They stay with it and can be used again once sharing stops.`;
|
|
9752
|
+
function pausedOwnCreditsText(_pool) {
|
|
9753
|
+
return ownCreditsFirstText();
|
|
9671
9754
|
}
|
|
9672
9755
|
function ownCreditsFirstText() {
|
|
9673
9756
|
return "This workspace uses its own credits first, then these shared credits.";
|
|
@@ -9862,25 +9945,36 @@ function PoolModalShell({
|
|
|
9862
9945
|
}
|
|
9863
9946
|
);
|
|
9864
9947
|
}
|
|
9865
|
-
function PoolWarning({ children }) {
|
|
9866
|
-
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
9867
|
-
"div",
|
|
9868
|
-
{
|
|
9869
|
-
role: "alert",
|
|
9870
|
-
className: "w-full",
|
|
9871
|
-
style: {
|
|
9872
|
-
...modalBodyText,
|
|
9873
|
-
color: T16.primary,
|
|
9874
|
-
background: T16.warningFill,
|
|
9875
|
-
border: `1px solid ${T16.warningBorder}`,
|
|
9876
|
-
borderRadius: T16.r3xl,
|
|
9877
|
-
padding: `${T16.spXl} ${T16.sp3xl}`
|
|
9878
|
-
},
|
|
9879
|
-
children
|
|
9880
|
-
}
|
|
9881
|
-
);
|
|
9882
|
-
}
|
|
9883
9948
|
var fieldLabel = { ...modalBodyText, fontWeight: 500, color: T16.primary };
|
|
9949
|
+
var fieldBox = {
|
|
9950
|
+
background: T16.fillPlus,
|
|
9951
|
+
height: 48,
|
|
9952
|
+
borderRadius: T16.r3xl,
|
|
9953
|
+
padding: `${T16.spXl} ${T16.sp3xl}`,
|
|
9954
|
+
gap: T16.spXl
|
|
9955
|
+
};
|
|
9956
|
+
var bareInput = {
|
|
9957
|
+
...modalBodyText,
|
|
9958
|
+
background: "transparent",
|
|
9959
|
+
border: "none",
|
|
9960
|
+
outline: "none",
|
|
9961
|
+
color: T16.primary,
|
|
9962
|
+
padding: 0
|
|
9963
|
+
};
|
|
9964
|
+
var EXPIRY_OPTIONS = [
|
|
9965
|
+
{ id: "never", label: "Never" },
|
|
9966
|
+
{ id: "month", label: "In 1 month" },
|
|
9967
|
+
{ id: "months", label: "In a number of months" },
|
|
9968
|
+
{ id: "year", label: "In 1 year" },
|
|
9969
|
+
{ id: "date", label: "On a date" }
|
|
9970
|
+
];
|
|
9971
|
+
var isExpiryKind = (id) => EXPIRY_OPTIONS.some((o) => o.id === id);
|
|
9972
|
+
var endsText = (member) => member.endsAt ? `, until ${formatPoolEndsAt(member.endsAt)}` : "";
|
|
9973
|
+
function endsAtHelp(kind, endsAt) {
|
|
9974
|
+
if (kind === "never") return "Shares every billing cycle until it is removed.";
|
|
9975
|
+
const stop = "After that, the other workspace spends only its own credits.";
|
|
9976
|
+
return endsAt ? `Sharing stops on ${formatPoolEndsAt(endsAt)}. ${stop}` : stop;
|
|
9977
|
+
}
|
|
9884
9978
|
function CreditPoolMemberModal(props) {
|
|
9885
9979
|
const { toast } = useSettingsAdapters();
|
|
9886
9980
|
const editing = props.kind === "edit" ? props.member : null;
|
|
@@ -9891,17 +9985,28 @@ function CreditPoolMemberModal(props) {
|
|
|
9891
9985
|
const [touched, setTouched] = (0, import_react20.useState)(false);
|
|
9892
9986
|
const [saving, setSaving] = (0, import_react20.useState)(false);
|
|
9893
9987
|
const [serverError, setServerError] = (0, import_react20.useState)(null);
|
|
9988
|
+
const initialExpiry = expiryChoiceFor(editing);
|
|
9989
|
+
const [expiryKind, setExpiryKind] = (0, import_react20.useState)(initialExpiry.kind);
|
|
9990
|
+
const [monthsRaw, setMonthsRaw] = (0, import_react20.useState)("3");
|
|
9991
|
+
const [endDate, setEndDate] = (0, import_react20.useState)(initialExpiry.kind === "date" ? initialExpiry.date : "");
|
|
9894
9992
|
(0, import_react20.useEffect)(() => {
|
|
9895
9993
|
setServerError(null);
|
|
9896
|
-
}, [memberId, mode, raw, note]);
|
|
9994
|
+
}, [memberId, mode, raw, note, expiryKind, monthsRaw, endDate]);
|
|
9897
9995
|
const value = validatePoolValue(mode, raw);
|
|
9898
9996
|
const noteCheck = validatePoolText(note, POOL_NOTE_MAX_LENGTH);
|
|
9899
|
-
const
|
|
9900
|
-
const
|
|
9997
|
+
const expiry = expiryKind === "months" ? { kind: "months", months: monthsRaw.trim() ? Number(monthsRaw) : NaN } : expiryKind === "date" ? { kind: "date", date: endDate } : { kind: expiryKind };
|
|
9998
|
+
const endsAtUnchanged = Boolean(editing) && expiry.kind === initialExpiry.kind && (expiry.kind !== "date" || initialExpiry.kind === "date" && expiry.date === initialExpiry.date);
|
|
9999
|
+
const endsAt = endsAtUnchanged ? null : poolEndsAtFrom(expiry);
|
|
10000
|
+
const splitChanged = !editing || mode !== editing.mode || !value.ok || value.value !== editing.value;
|
|
10001
|
+
const changed = splitChanged || !endsAtUnchanged;
|
|
10002
|
+
const valid = value.ok && (endsAt === null || endsAt.ok) && (props.kind === "edit" || Boolean(memberId) && noteCheck.ok);
|
|
9901
10003
|
const canSave = !saving && changed && valid;
|
|
9902
10004
|
const valueHint = touched && !value.ok ? value.reason : null;
|
|
10005
|
+
const expiryHint = endsAt && !endsAt.ok && !(expiry.kind === "date" && !expiry.date) ? endsAt.reason : null;
|
|
9903
10006
|
const handleSave = async () => {
|
|
9904
10007
|
if (!canSave || !value.ok) return;
|
|
10008
|
+
const sendEndsAt = endsAtUnchanged ? null : poolEndsAtFrom(expiry);
|
|
10009
|
+
if (sendEndsAt && !sendEndsAt.ok) return;
|
|
9905
10010
|
setSaving(true);
|
|
9906
10011
|
try {
|
|
9907
10012
|
if (props.kind === "add") {
|
|
@@ -9909,12 +10014,17 @@ function CreditPoolMemberModal(props) {
|
|
|
9909
10014
|
memberWorkspaceId: memberId,
|
|
9910
10015
|
mode,
|
|
9911
10016
|
value: value.value,
|
|
9912
|
-
note: noteCheck.ok ? noteCheck.value : ""
|
|
10017
|
+
note: noteCheck.ok ? noteCheck.value : "",
|
|
10018
|
+
...sendEndsAt?.value ? { endsAt: sendEndsAt.value } : {}
|
|
9913
10019
|
});
|
|
9914
|
-
toast.success(`Credits shared. ${describeAllowance(added)}.`);
|
|
10020
|
+
toast.success(`Credits shared. ${describeAllowance(added)}${endsText(added)}.`);
|
|
9915
10021
|
} else {
|
|
9916
|
-
const updated = await props.onSave({
|
|
9917
|
-
|
|
10022
|
+
const updated = await props.onSave({
|
|
10023
|
+
mode,
|
|
10024
|
+
value: value.value,
|
|
10025
|
+
...sendEndsAt ? { endsAt: sendEndsAt.value } : {}
|
|
10026
|
+
});
|
|
10027
|
+
toast.success(`Share updated. ${describeAllowance(updated)}${endsText(updated)}.`);
|
|
9918
10028
|
}
|
|
9919
10029
|
props.onSaved();
|
|
9920
10030
|
props.onClose();
|
|
@@ -9999,11 +10109,7 @@ function CreditPoolMemberModal(props) {
|
|
|
9999
10109
|
{
|
|
10000
10110
|
className: "flex items-center w-full",
|
|
10001
10111
|
style: {
|
|
10002
|
-
|
|
10003
|
-
height: 48,
|
|
10004
|
-
borderRadius: T16.r3xl,
|
|
10005
|
-
padding: `${T16.spXl} ${T16.sp3xl}`,
|
|
10006
|
-
gap: T16.spXl,
|
|
10112
|
+
...fieldBox,
|
|
10007
10113
|
border: valueHint ? `1px solid ${T16.error}` : "1px solid transparent"
|
|
10008
10114
|
},
|
|
10009
10115
|
children: [
|
|
@@ -10021,14 +10127,7 @@ function CreditPoolMemberModal(props) {
|
|
|
10021
10127
|
setTouched(true);
|
|
10022
10128
|
},
|
|
10023
10129
|
className: "flex-1 min-w-0",
|
|
10024
|
-
style:
|
|
10025
|
-
...modalBodyText,
|
|
10026
|
-
background: "transparent",
|
|
10027
|
-
border: "none",
|
|
10028
|
-
outline: "none",
|
|
10029
|
-
color: T16.primary,
|
|
10030
|
-
padding: 0
|
|
10031
|
-
}
|
|
10130
|
+
style: bareInput
|
|
10032
10131
|
}
|
|
10033
10132
|
),
|
|
10034
10133
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "shrink-0", style: { ...modalBodyText, color: T16.muted }, children: mode === "percent" ? "%" : "credits" })
|
|
@@ -10036,10 +10135,76 @@ function CreditPoolMemberModal(props) {
|
|
|
10036
10135
|
}
|
|
10037
10136
|
),
|
|
10038
10137
|
valueHint ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { role: "alert", style: { ...modalBodyText, color: T16.error }, children: valueHint }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { style: { ...modalBodyText, color: T16.tertiary }, children: [
|
|
10039
|
-
mode === "percent" ? "A share of this workspace's plan credits for each billing cycle. Credits stay with this workspace; the other workspace spends them up to this share." : "Credits the other workspace may spend each billing cycle. Credits stay with this workspace until spent.",
|
|
10138
|
+
mode === "percent" ? "A share of this workspace's plan credits for each billing cycle. Credits stay with this workspace; the other workspace spends them up to this share, after its own credits." : "Credits the other workspace may spend each billing cycle, after its own credits. Credits stay with this workspace until spent.",
|
|
10040
10139
|
editing ? " Applies immediately." : ""
|
|
10041
10140
|
] })
|
|
10042
10141
|
] }),
|
|
10142
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col w-full", style: { gap: T16.spMd }, children: [
|
|
10143
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { style: fieldLabel, children: "Ends" }),
|
|
10144
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
10145
|
+
import_ui14.ScSelect,
|
|
10146
|
+
{
|
|
10147
|
+
value: expiryKind,
|
|
10148
|
+
onChange: (id) => {
|
|
10149
|
+
if (isExpiryKind(id)) setExpiryKind(id);
|
|
10150
|
+
},
|
|
10151
|
+
options: EXPIRY_OPTIONS,
|
|
10152
|
+
disabled: saving
|
|
10153
|
+
}
|
|
10154
|
+
),
|
|
10155
|
+
expiryKind === "months" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
10156
|
+
"div",
|
|
10157
|
+
{
|
|
10158
|
+
className: "flex items-center w-full",
|
|
10159
|
+
style: {
|
|
10160
|
+
...fieldBox,
|
|
10161
|
+
border: expiryHint ? `1px solid ${T16.error}` : "1px solid transparent"
|
|
10162
|
+
},
|
|
10163
|
+
children: [
|
|
10164
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
10165
|
+
"input",
|
|
10166
|
+
{
|
|
10167
|
+
inputMode: "numeric",
|
|
10168
|
+
"aria-label": "Number of months",
|
|
10169
|
+
"aria-invalid": expiryHint ? true : void 0,
|
|
10170
|
+
placeholder: "Enter a number of months",
|
|
10171
|
+
value: monthsRaw,
|
|
10172
|
+
disabled: saving,
|
|
10173
|
+
onChange: (e) => setMonthsRaw(e.target.value.replace(/\D/g, "").slice(0, 3)),
|
|
10174
|
+
className: "flex-1 min-w-0",
|
|
10175
|
+
style: bareInput
|
|
10176
|
+
}
|
|
10177
|
+
),
|
|
10178
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "shrink-0", style: { ...modalBodyText, color: T16.muted }, children: "months" })
|
|
10179
|
+
]
|
|
10180
|
+
}
|
|
10181
|
+
),
|
|
10182
|
+
expiryKind === "date" && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
10183
|
+
"div",
|
|
10184
|
+
{
|
|
10185
|
+
className: "flex items-center w-full",
|
|
10186
|
+
style: {
|
|
10187
|
+
...fieldBox,
|
|
10188
|
+
border: expiryHint ? `1px solid ${T16.error}` : "1px solid transparent"
|
|
10189
|
+
},
|
|
10190
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
10191
|
+
"input",
|
|
10192
|
+
{
|
|
10193
|
+
type: "date",
|
|
10194
|
+
"aria-label": "End date",
|
|
10195
|
+
"aria-invalid": expiryHint ? true : void 0,
|
|
10196
|
+
min: minPoolEndDate(),
|
|
10197
|
+
value: endDate,
|
|
10198
|
+
disabled: saving,
|
|
10199
|
+
onChange: (e) => setEndDate(e.target.value),
|
|
10200
|
+
className: "flex-1 min-w-0",
|
|
10201
|
+
style: { ...bareInput, colorScheme: "light dark" }
|
|
10202
|
+
}
|
|
10203
|
+
)
|
|
10204
|
+
}
|
|
10205
|
+
),
|
|
10206
|
+
expiryHint ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { role: "alert", style: { ...modalBodyText, color: T16.error }, children: expiryHint }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { style: { ...modalBodyText, color: T16.tertiary }, children: endsAtHelp(expiryKind, endsAtUnchanged ? editing?.endsAt ?? null : endsAt?.ok ? endsAt.value : null) })
|
|
10207
|
+
] }),
|
|
10043
10208
|
props.kind === "add" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col w-full", style: { gap: T16.spXs }, children: [
|
|
10044
10209
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { style: fieldLabel, children: "Note" }),
|
|
10045
10210
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
@@ -10061,7 +10226,6 @@ function CreditPoolMemberModal(props) {
|
|
|
10061
10226
|
POOL_NOTE_MAX_LENGTH
|
|
10062
10227
|
] })
|
|
10063
10228
|
] }),
|
|
10064
|
-
props.kind === "add" && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PoolWarning, { children: "While it spends shared credits, the other workspace uses only this workspace's credits, not its own." }),
|
|
10065
10229
|
serverError && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { role: "alert", style: { ...modalBodyText, color: T16.error }, children: serverError })
|
|
10066
10230
|
]
|
|
10067
10231
|
}
|
|
@@ -10182,7 +10346,9 @@ var T17 = {
|
|
|
10182
10346
|
r3xl: "var(--radius-3xl)",
|
|
10183
10347
|
rFull: "var(--radius-full)"
|
|
10184
10348
|
};
|
|
10185
|
-
var MEMBER_COLUMNS2 = "minmax(
|
|
10349
|
+
var MEMBER_COLUMNS2 = "minmax(180px, 1fr) 150px 80px 90px 110px 150px";
|
|
10350
|
+
var MEMBER_GAP = 16;
|
|
10351
|
+
var MEMBER_MIN_WIDTH = 880;
|
|
10186
10352
|
var cellText2 = {
|
|
10187
10353
|
fontFamily: T17.font,
|
|
10188
10354
|
fontSize: T17.fsSm,
|
|
@@ -10195,7 +10361,7 @@ var tableHeader = (columns, labels) => /* @__PURE__ */ (0, import_jsx_runtime28.
|
|
|
10195
10361
|
style: {
|
|
10196
10362
|
display: "grid",
|
|
10197
10363
|
gridTemplateColumns: columns,
|
|
10198
|
-
gap:
|
|
10364
|
+
gap: MEMBER_GAP,
|
|
10199
10365
|
padding: "8px 16px",
|
|
10200
10366
|
fontSize: 11,
|
|
10201
10367
|
color: T17.muted,
|
|
@@ -10219,17 +10385,21 @@ function MemberRow2({
|
|
|
10219
10385
|
gridTemplateColumns: MEMBER_COLUMNS2,
|
|
10220
10386
|
alignItems: "center",
|
|
10221
10387
|
padding: `10px ${T17.sp3xl}`,
|
|
10222
|
-
gap:
|
|
10388
|
+
gap: MEMBER_GAP
|
|
10223
10389
|
},
|
|
10224
10390
|
children: [
|
|
10225
10391
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col min-w-0", style: { gap: 2 }, children: [
|
|
10226
10392
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "truncate", style: { ...cellText2, fontWeight: 500 }, children: poolWorkspaceName(member.memberWorkspaceName) }),
|
|
10227
10393
|
member.note && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "truncate", title: member.note, style: { ...cellText2, color: T17.tertiary }, children: member.note })
|
|
10228
10394
|
] }),
|
|
10229
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.
|
|
10395
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col min-w-0", style: { gap: 2 }, children: [
|
|
10396
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { style: cellText2, children: formatPoolSplit({ mode: "fixed", value: member.allowance }) }),
|
|
10397
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { style: { ...cellText2, color: T17.tertiary }, children: member.mode === "percent" ? `${formatPoolSplit(member)} \xB7 this cycle` : "this cycle" })
|
|
10398
|
+
] }),
|
|
10230
10399
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { style: cellText2, children: formatCredits(member.used) }),
|
|
10231
10400
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { style: { ...cellText2, color: spent ? T17.warning : T17.primary }, children: formatCredits(member.remaining) }),
|
|
10232
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.
|
|
10401
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { style: { ...cellText2, color: member.endsAt ? T17.primary : T17.muted }, children: formatPoolEndsAt(member.endsAt) }),
|
|
10402
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-center whitespace-nowrap", style: { gap: 8 }, children: [
|
|
10233
10403
|
onEdit && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_ui16.ScButton, { text: "Edit", variant: "secondary", size: "sm", onClick: onEdit }),
|
|
10234
10404
|
onRemove && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_ui16.ScButton, { text: "Remove", variant: "secondary", size: "sm", onClick: onRemove })
|
|
10235
10405
|
] })
|
|
@@ -10355,11 +10525,13 @@ function SharedCreditsView() {
|
|
|
10355
10525
|
remaining: sponsor.remaining
|
|
10356
10526
|
}) }),
|
|
10357
10527
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { style: { ...cellText2, color: T17.muted }, children: [
|
|
10358
|
-
"This workspace
|
|
10528
|
+
"This workspace uses its own credits first, then",
|
|
10529
|
+
" ",
|
|
10359
10530
|
poolWorkspaceName(sponsor.sponsorWorkspaceName),
|
|
10360
|
-
"'s
|
|
10361
|
-
sponsor.cycle?.end ? `,
|
|
10362
|
-
"."
|
|
10531
|
+
"'s, up to its allowance",
|
|
10532
|
+
sponsor.cycle?.end && poolRenewsAtCycleEnd({ cycleEnd: sponsor.cycle.end, endsAt: sponsor.endsAt }) ? `, which starts again on ${formatDate2(sponsor.cycle.end)}` : "",
|
|
10533
|
+
". ",
|
|
10534
|
+
sharedPoolEndsText(sponsor)
|
|
10363
10535
|
] })
|
|
10364
10536
|
]
|
|
10365
10537
|
}
|
|
@@ -10371,8 +10543,8 @@ function SharedCreditsView() {
|
|
|
10371
10543
|
{
|
|
10372
10544
|
grow: "cap",
|
|
10373
10545
|
maxHeight: 420,
|
|
10374
|
-
contentMinWidth:
|
|
10375
|
-
header: tableHeader(MEMBER_COLUMNS2, ["Workspace", "Allowance", "Used", "Remaining", "Actions"]),
|
|
10546
|
+
contentMinWidth: MEMBER_MIN_WIDTH,
|
|
10547
|
+
header: tableHeader(MEMBER_COLUMNS2, ["Workspace", "Allowance", "Used", "Remaining", "Ends", "Actions"]),
|
|
10376
10548
|
isEmpty: failed || members.length === 0,
|
|
10377
10549
|
emptyText: failed ? "Couldn't load shared credits. Try again later." : "This workspace doesn't share its credits with any other workspace.",
|
|
10378
10550
|
children: members.map((member) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
@@ -10422,6 +10594,71 @@ function SharedCreditsView() {
|
|
|
10422
10594
|
] });
|
|
10423
10595
|
}
|
|
10424
10596
|
|
|
10597
|
+
// src/entitlement.ts
|
|
10598
|
+
function parseBillingEntitlement(value) {
|
|
10599
|
+
if (!value || typeof value !== "object") return null;
|
|
10600
|
+
const raw = value;
|
|
10601
|
+
if (typeof raw.paid !== "boolean") return null;
|
|
10602
|
+
const source = raw.source === "plan" || raw.source === "pool" ? raw.source : null;
|
|
10603
|
+
const entitlement = { paid: raw.paid, source };
|
|
10604
|
+
if (typeof raw.sponsorWorkspaceId === "string") entitlement.sponsorWorkspaceId = raw.sponsorWorkspaceId;
|
|
10605
|
+
if (typeof raw.sponsorName === "string") entitlement.sponsorName = raw.sponsorName;
|
|
10606
|
+
if (typeof raw.endsAt === "string" || raw.endsAt === null) entitlement.endsAt = raw.endsAt;
|
|
10607
|
+
return entitlement;
|
|
10608
|
+
}
|
|
10609
|
+
function entitlementFromBody(body) {
|
|
10610
|
+
if (!body || typeof body !== "object") return null;
|
|
10611
|
+
return parseBillingEntitlement(body.entitlement);
|
|
10612
|
+
}
|
|
10613
|
+
function entitlementFromFailure(failure) {
|
|
10614
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10615
|
+
const visit = (value, depth) => {
|
|
10616
|
+
if (depth > 4 || value == null || typeof value !== "object" || seen.has(value)) return null;
|
|
10617
|
+
seen.add(value);
|
|
10618
|
+
const found = entitlementFromBody(value);
|
|
10619
|
+
if (found) return found;
|
|
10620
|
+
const error = value;
|
|
10621
|
+
const response = error.response;
|
|
10622
|
+
for (const child of [error.body, error.data, response?.data, error.cause]) {
|
|
10623
|
+
const nested = visit(child, depth + 1);
|
|
10624
|
+
if (nested) return nested;
|
|
10625
|
+
}
|
|
10626
|
+
return null;
|
|
10627
|
+
};
|
|
10628
|
+
return visit(failure, 0);
|
|
10629
|
+
}
|
|
10630
|
+
function isPaidPlan(subscription) {
|
|
10631
|
+
const amount = subscription?.plan?.amount;
|
|
10632
|
+
return amount != null && amount > 0;
|
|
10633
|
+
}
|
|
10634
|
+
function hasPaidFeatures({
|
|
10635
|
+
entitlement,
|
|
10636
|
+
subscription
|
|
10637
|
+
}) {
|
|
10638
|
+
return entitlement ? entitlement.paid : isPaidPlan(subscription);
|
|
10639
|
+
}
|
|
10640
|
+
function isSponsoredEntitlement(entitlement) {
|
|
10641
|
+
return entitlement?.source === "pool" && entitlement.paid;
|
|
10642
|
+
}
|
|
10643
|
+
function sponsoredCreditsText(entitlement) {
|
|
10644
|
+
const sponsor = entitlement.sponsorName?.trim() || "another workspace";
|
|
10645
|
+
const ends = entitlement.endsAt ? ` Sharing ends on ${formatPoolEndsAt(entitlement.endsAt)}.` : "";
|
|
10646
|
+
return `Credits shared by ${sponsor}.${ends}`;
|
|
10647
|
+
}
|
|
10648
|
+
async function loadCurrentPlan(fetchCurrentPlan) {
|
|
10649
|
+
let response;
|
|
10650
|
+
try {
|
|
10651
|
+
response = await fetchCurrentPlan();
|
|
10652
|
+
} catch (failure) {
|
|
10653
|
+
const entitlement2 = entitlementFromFailure(failure);
|
|
10654
|
+
if (!entitlement2) throw failure;
|
|
10655
|
+
return { subscription: null, entitlement: entitlement2, paid: entitlement2.paid };
|
|
10656
|
+
}
|
|
10657
|
+
const subscription = response?.data ?? null;
|
|
10658
|
+
const entitlement = entitlementFromBody(response);
|
|
10659
|
+
return { subscription, entitlement, paid: hasPaidFeatures({ entitlement, subscription }) };
|
|
10660
|
+
}
|
|
10661
|
+
|
|
10425
10662
|
// src/billing-content.tsx
|
|
10426
10663
|
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
10427
10664
|
var DEFAULT_TOPUP_SERVICE = "catalogix";
|
|
@@ -11553,7 +11790,8 @@ function BillingContent({
|
|
|
11553
11790
|
showPerUserLimits: showPerUserLimitsProp,
|
|
11554
11791
|
onShowPerUserLimitsChange,
|
|
11555
11792
|
showSharedCredits: showSharedCreditsProp,
|
|
11556
|
-
onShowSharedCreditsChange
|
|
11793
|
+
onShowSharedCreditsChange,
|
|
11794
|
+
onEntitlementChange
|
|
11557
11795
|
} = {}) {
|
|
11558
11796
|
const { auth, workspace, organization, api, toast, navigation } = useSettingsAdapters();
|
|
11559
11797
|
const user = auth.user;
|
|
@@ -11592,6 +11830,9 @@ function BillingContent({
|
|
|
11592
11830
|
const [showExportModal, setShowExportModal] = (0, import_react23.useState)(false);
|
|
11593
11831
|
const [showBuyCreditsModal, setShowBuyCreditsModal] = (0, import_react23.useState)(false);
|
|
11594
11832
|
const [subscription, setSubscription] = (0, import_react23.useState)(null);
|
|
11833
|
+
const [entitlement, setEntitlement] = (0, import_react23.useState)(
|
|
11834
|
+
null
|
|
11835
|
+
);
|
|
11595
11836
|
const [availableCredits, setAvailableCredits] = (0, import_react23.useState)(null);
|
|
11596
11837
|
const [sharedPool, setSharedPool] = (0, import_react23.useState)(null);
|
|
11597
11838
|
const [usedByNames, setUsedByNames] = (0, import_react23.useState)({});
|
|
@@ -11637,12 +11878,15 @@ function BillingContent({
|
|
|
11637
11878
|
try {
|
|
11638
11879
|
console.log("calling Billing apis");
|
|
11639
11880
|
const [subRes, creditsRes, productsRes, customRes] = await Promise.all([
|
|
11640
|
-
|
|
11881
|
+
// A sponsored workspace with no subscription of its own gets a 404
|
|
11882
|
+
// that carries its entitlement: loadCurrentPlan answers it, not throws.
|
|
11883
|
+
loadCurrentPlan(api.fetchCurrentPlan).catch(() => null),
|
|
11641
11884
|
api.fetchAvailableCredits().catch(() => null),
|
|
11642
11885
|
api.fetchPlans().catch(() => null),
|
|
11643
11886
|
api.getCustomCreditInfo?.().catch(() => null) ?? Promise.resolve(null)
|
|
11644
11887
|
]);
|
|
11645
|
-
if (subRes?.
|
|
11888
|
+
if (subRes?.subscription) setSubscription(subRes.subscription);
|
|
11889
|
+
if (subRes) setEntitlement(subRes.entitlement);
|
|
11646
11890
|
if (creditsRes?.availableCredits != null)
|
|
11647
11891
|
setAvailableCredits(creditsRes.availableCredits);
|
|
11648
11892
|
setSharedPool(creditsRes?.sharedPool ?? null);
|
|
@@ -11812,6 +12056,7 @@ function BillingContent({
|
|
|
11812
12056
|
setInitialFetchTriggered(false);
|
|
11813
12057
|
setBillingOverviewLoaded(false);
|
|
11814
12058
|
setSubscription(null);
|
|
12059
|
+
setEntitlement(null);
|
|
11815
12060
|
setAvailableCredits(null);
|
|
11816
12061
|
setProducts([]);
|
|
11817
12062
|
setTotalCredits(null);
|
|
@@ -11867,7 +12112,16 @@ function BillingContent({
|
|
|
11867
12112
|
subscription?.scheduledDowngradeEffectiveDate
|
|
11868
12113
|
);
|
|
11869
12114
|
const scheduledDowngradeText = subscription?.downgradeScheduled && subscription.plan?.name ? `Downgrades to ${subscription.plan.name}${scheduledDowngradeDateLabel ? ` ${scheduledDowngradeDateLabel}` : ""}` : void 0;
|
|
11870
|
-
const
|
|
12115
|
+
const sponsored = isSponsoredEntitlement(entitlement);
|
|
12116
|
+
const sponsoredWithoutPlan = sponsored && billingOverviewLoaded && !loadingBilling && subscription == null;
|
|
12117
|
+
const isPlanDetailsLoading = sponsoredWithoutPlan ? false : !billingOverviewLoaded || loadingBilling || subscription?.plan == null || !planName || planName === "-" || !planAmount || currentPlanCredits == null;
|
|
12118
|
+
const paidFeatures = hasPaidFeatures({ entitlement, subscription });
|
|
12119
|
+
const onEntitlementChangeRef = (0, import_react23.useRef)(onEntitlementChange);
|
|
12120
|
+
onEntitlementChangeRef.current = onEntitlementChange;
|
|
12121
|
+
(0, import_react23.useEffect)(() => {
|
|
12122
|
+
if (!billingOverviewLoaded) return;
|
|
12123
|
+
onEntitlementChangeRef.current?.({ entitlement, paid: paidFeatures });
|
|
12124
|
+
}, [billingOverviewLoaded, entitlement, paidFeatures]);
|
|
11871
12125
|
const {
|
|
11872
12126
|
used: usedCredits,
|
|
11873
12127
|
remaining: remainingCredits,
|
|
@@ -12104,9 +12358,9 @@ function BillingContent({
|
|
|
12104
12358
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
12105
12359
|
import_ui17.ScPlanDetailsCard,
|
|
12106
12360
|
{
|
|
12107
|
-
planName,
|
|
12108
|
-
planCredits: planCreditsText,
|
|
12109
|
-
planPrice: planAmount,
|
|
12361
|
+
planName: sponsoredWithoutPlan ? "Free" : planName,
|
|
12362
|
+
planCredits: sponsoredWithoutPlan ? "Shared credits" : planCreditsText,
|
|
12363
|
+
planPrice: sponsoredWithoutPlan ? `${workspace.current?.country?.trim().toUpperCase() === "IN" ? "\u20B9" : "$"}0.00 / month` : planAmount,
|
|
12110
12364
|
badgeText: "Active",
|
|
12111
12365
|
badgeSubText: scheduledDowngradeText,
|
|
12112
12366
|
currentPlanLabel: "Current plan",
|
|
@@ -12188,12 +12442,57 @@ function BillingContent({
|
|
|
12188
12442
|
},
|
|
12189
12443
|
children: [
|
|
12190
12444
|
ownCreditsFirstText(),
|
|
12191
|
-
sharedPool
|
|
12445
|
+
poolRenewsAtCycleEnd(sharedPool) ? ` The allowance starts again on ${formatDate3(sharedPool.cycleEnd)}.` : "",
|
|
12446
|
+
` ${sharedPoolEndsText(sharedPool)}`
|
|
12192
12447
|
]
|
|
12193
12448
|
}
|
|
12194
12449
|
)
|
|
12195
12450
|
]
|
|
12196
12451
|
}
|
|
12452
|
+
) : sponsored && entitlement ? (
|
|
12453
|
+
// Billing says a pool entitles it, but the balance carried no
|
|
12454
|
+
// allowance (an older credits answer, or it failed): say whose.
|
|
12455
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
12456
|
+
"div",
|
|
12457
|
+
{
|
|
12458
|
+
role: "status",
|
|
12459
|
+
className: "flex flex-col shrink-0 w-full",
|
|
12460
|
+
style: {
|
|
12461
|
+
gap: 4,
|
|
12462
|
+
padding: 16,
|
|
12463
|
+
backgroundColor: "var(--alias-surface-base)",
|
|
12464
|
+
border: "1px solid var(--alias-border-subtle)",
|
|
12465
|
+
borderRadius: "var(--radius-3xl)"
|
|
12466
|
+
},
|
|
12467
|
+
children: [
|
|
12468
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
12469
|
+
"span",
|
|
12470
|
+
{
|
|
12471
|
+
style: {
|
|
12472
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
12473
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
12474
|
+
fontWeight: 500,
|
|
12475
|
+
lineHeight: "var(--line-height-line-height-sm)",
|
|
12476
|
+
color: "var(--alias-text---icons-primary)"
|
|
12477
|
+
},
|
|
12478
|
+
children: sponsoredCreditsText(entitlement)
|
|
12479
|
+
}
|
|
12480
|
+
),
|
|
12481
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
12482
|
+
"span",
|
|
12483
|
+
{
|
|
12484
|
+
style: {
|
|
12485
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
12486
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
12487
|
+
lineHeight: "var(--line-height-line-height-sm)",
|
|
12488
|
+
color: "var(--alias-text---icons-muted)"
|
|
12489
|
+
},
|
|
12490
|
+
children: ownCreditsFirstText()
|
|
12491
|
+
}
|
|
12492
|
+
)
|
|
12493
|
+
]
|
|
12494
|
+
}
|
|
12495
|
+
)
|
|
12197
12496
|
) : null,
|
|
12198
12497
|
usage ? /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
12199
12498
|
"div",
|
|
@@ -12436,7 +12735,7 @@ var import_react24 = require("react");
|
|
|
12436
12735
|
var import_ui18 = require("@streamoid/ui");
|
|
12437
12736
|
var import_icons16 = require("@streamoid/icons");
|
|
12438
12737
|
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
12439
|
-
var
|
|
12738
|
+
var EXPIRY_OPTIONS2 = [
|
|
12440
12739
|
{ label: "30 days", value: "30d" },
|
|
12441
12740
|
{ label: "60 days", value: "60d" },
|
|
12442
12741
|
{ label: "90 days", value: "90d" },
|
|
@@ -12627,7 +12926,7 @@ function CreateTokenModal({ onClose, onCreated }) {
|
|
|
12627
12926
|
children: "Expiry"
|
|
12628
12927
|
}
|
|
12629
12928
|
) }),
|
|
12630
|
-
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { style: { display: "flex", gap: "var(--spacing-md)", flexWrap: "wrap" }, children:
|
|
12929
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { style: { display: "flex", gap: "var(--spacing-md)", flexWrap: "wrap" }, children: EXPIRY_OPTIONS2.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
12631
12930
|
import_ui18.ScButton,
|
|
12632
12931
|
{
|
|
12633
12932
|
text: opt.label,
|
|
@@ -16568,6 +16867,30 @@ function OrganizationPicker({
|
|
|
16568
16867
|
);
|
|
16569
16868
|
}
|
|
16570
16869
|
|
|
16870
|
+
// src/use-billing-entitlement.ts
|
|
16871
|
+
var import_react30 = require("react");
|
|
16872
|
+
function useBillingEntitlement(fetchCurrentPlan, key) {
|
|
16873
|
+
const fetchRef = (0, import_react30.useRef)(fetchCurrentPlan);
|
|
16874
|
+
fetchRef.current = fetchCurrentPlan;
|
|
16875
|
+
const [state, setState] = (0, import_react30.useState)(null);
|
|
16876
|
+
const [loading, setLoading] = (0, import_react30.useState)(false);
|
|
16877
|
+
(0, import_react30.useEffect)(() => {
|
|
16878
|
+
const fetch2 = fetchRef.current;
|
|
16879
|
+
setState(null);
|
|
16880
|
+
if (!key || !fetch2) {
|
|
16881
|
+
setLoading(false);
|
|
16882
|
+
return;
|
|
16883
|
+
}
|
|
16884
|
+
let live = true;
|
|
16885
|
+
setLoading(true);
|
|
16886
|
+
loadCurrentPlan(fetch2).then((next) => live && setState(next)).catch(() => live && setState(null)).finally(() => live && setLoading(false));
|
|
16887
|
+
return () => {
|
|
16888
|
+
live = false;
|
|
16889
|
+
};
|
|
16890
|
+
}, [key]);
|
|
16891
|
+
return { state, loading };
|
|
16892
|
+
}
|
|
16893
|
+
|
|
16571
16894
|
// src/administration-navigation.ts
|
|
16572
16895
|
var normalizedBase = (base) => base.replace(/\/$/, "");
|
|
16573
16896
|
var returnKey = (base, entryKey) => `streamoid:settings:return:${base}:${entryKey}`;
|
|
@@ -16614,7 +16937,7 @@ function readSettingsCaller(base, state, entryKey, fallback = `${normalizedBase(
|
|
|
16614
16937
|
}
|
|
16615
16938
|
|
|
16616
16939
|
// src/app-settings-page.tsx
|
|
16617
|
-
var
|
|
16940
|
+
var import_react31 = require("react");
|
|
16618
16941
|
var import_icons20 = require("@streamoid/icons");
|
|
16619
16942
|
|
|
16620
16943
|
// src/app-settings-page.module.css
|
|
@@ -16677,7 +17000,7 @@ function AppSettingsSection({ title, action, children }) {
|
|
|
16677
17000
|
] });
|
|
16678
17001
|
}
|
|
16679
17002
|
function AppSettingsRow({ title, description, summary, href, onClick, disabled, disabledReason, ariaLabel, trailing }) {
|
|
16680
|
-
const reasonId = (0,
|
|
17003
|
+
const reasonId = (0, import_react31.useId)();
|
|
16681
17004
|
const content = /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
16682
17005
|
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: app_settings_page_default.rowCopy, children: [
|
|
16683
17006
|
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: app_settings_page_default.rowTitle, children: title }),
|