@kerne/react 1.0.0 → 1.1.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/{chunk-NFJ2S5VJ.js → chunk-IZMRK3WK.js} +63 -0
- package/dist/{chunk-IMZFZ3P5.cjs → chunk-TYNZ2WU7.cjs} +69 -6
- package/dist/{i18n-Di5qlnL1.d.cts → i18n-QilNgwqe.d.cts} +5 -0
- package/dist/{i18n-Di5qlnL1.d.ts → i18n-QilNgwqe.d.ts} +5 -0
- package/dist/index.cjs +10 -8
- package/dist/index.d.cts +49 -4
- package/dist/index.d.ts +49 -4
- package/dist/index.js +3 -1
- package/dist/ui/index.cjs +220 -194
- package/dist/ui/index.d.cts +79 -7
- package/dist/ui/index.d.ts +79 -7
- package/dist/ui/index.js +110 -84
- package/package.json +3 -3
|
@@ -194,6 +194,11 @@ var defaultLocalization = {
|
|
|
194
194
|
changePlan: "Change plan",
|
|
195
195
|
current: "Current",
|
|
196
196
|
switchTo: "Switch",
|
|
197
|
+
switching: "Switching...",
|
|
198
|
+
switchConfirmTitle: "Switch to {plan}?",
|
|
199
|
+
switchConfirmBody: "This applies right away, and your next invoice reflects the price difference for the rest of this period.",
|
|
200
|
+
switchConfirmButton: "Yes, switch",
|
|
201
|
+
switchConfirmDismiss: "Never mind",
|
|
197
202
|
noPlans: "No other plans are available right now.",
|
|
198
203
|
notOnInterval: "Not available on this interval",
|
|
199
204
|
loadFailed: "Could not load your plan right now.",
|
|
@@ -981,6 +986,63 @@ function useChangePlan() {
|
|
|
981
986
|
);
|
|
982
987
|
return { changePlan, isChanging };
|
|
983
988
|
}
|
|
989
|
+
function usePlanSwitch(subscription, refetchSubscription, options) {
|
|
990
|
+
const { openCheckout } = useCheckout();
|
|
991
|
+
const { changePlan } = useChangePlan();
|
|
992
|
+
const [pending, setPending] = useState(null);
|
|
993
|
+
const [switching, setSwitching] = useState(false);
|
|
994
|
+
const [switchError, setSwitchError] = useState(null);
|
|
995
|
+
const [checkoutPriceId, setCheckoutPriceId] = useState(null);
|
|
996
|
+
const [checkoutError, setCheckoutError] = useState(null);
|
|
997
|
+
const successUrl = options?.successUrl;
|
|
998
|
+
const cancelUrl = options?.cancelUrl;
|
|
999
|
+
const selectPlan = useCallback2(
|
|
1000
|
+
async (plan, price) => {
|
|
1001
|
+
if (subscription) {
|
|
1002
|
+
setSwitchError(null);
|
|
1003
|
+
setPending({ plan, price });
|
|
1004
|
+
return;
|
|
1005
|
+
}
|
|
1006
|
+
setCheckoutError(null);
|
|
1007
|
+
setCheckoutPriceId(price.id);
|
|
1008
|
+
try {
|
|
1009
|
+
await openCheckout(price.id, { successUrl, cancelUrl });
|
|
1010
|
+
} catch (e) {
|
|
1011
|
+
setCheckoutError(e);
|
|
1012
|
+
setCheckoutPriceId(null);
|
|
1013
|
+
}
|
|
1014
|
+
},
|
|
1015
|
+
[subscription, openCheckout, successUrl, cancelUrl]
|
|
1016
|
+
);
|
|
1017
|
+
const confirmSwitch = useCallback2(async () => {
|
|
1018
|
+
if (!pending || !subscription) return;
|
|
1019
|
+
setSwitching(true);
|
|
1020
|
+
setSwitchError(null);
|
|
1021
|
+
try {
|
|
1022
|
+
await changePlan(subscription.id, pending.price.id);
|
|
1023
|
+
setPending(null);
|
|
1024
|
+
refetchSubscription();
|
|
1025
|
+
} catch (e) {
|
|
1026
|
+
setSwitchError(e);
|
|
1027
|
+
} finally {
|
|
1028
|
+
setSwitching(false);
|
|
1029
|
+
}
|
|
1030
|
+
}, [pending, subscription, changePlan, refetchSubscription]);
|
|
1031
|
+
const dismissSwitch = useCallback2(() => {
|
|
1032
|
+
setPending(null);
|
|
1033
|
+
setSwitchError(null);
|
|
1034
|
+
}, []);
|
|
1035
|
+
return {
|
|
1036
|
+
pending,
|
|
1037
|
+
switching,
|
|
1038
|
+
switchError,
|
|
1039
|
+
checkoutPriceId,
|
|
1040
|
+
checkoutError,
|
|
1041
|
+
selectPlan,
|
|
1042
|
+
confirmSwitch,
|
|
1043
|
+
dismissSwitch
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
984
1046
|
function useAccess(featureKey, requested) {
|
|
985
1047
|
const client = useClient();
|
|
986
1048
|
const [state, setState] = useState({
|
|
@@ -1210,6 +1272,7 @@ export {
|
|
|
1210
1272
|
usePortal,
|
|
1211
1273
|
useCancelSubscription,
|
|
1212
1274
|
useChangePlan,
|
|
1275
|
+
usePlanSwitch,
|
|
1213
1276
|
useAccess,
|
|
1214
1277
|
useSubscription,
|
|
1215
1278
|
usePlans,
|
|
@@ -194,6 +194,11 @@ var defaultLocalization = {
|
|
|
194
194
|
changePlan: "Change plan",
|
|
195
195
|
current: "Current",
|
|
196
196
|
switchTo: "Switch",
|
|
197
|
+
switching: "Switching...",
|
|
198
|
+
switchConfirmTitle: "Switch to {plan}?",
|
|
199
|
+
switchConfirmBody: "This applies right away, and your next invoice reflects the price difference for the rest of this period.",
|
|
200
|
+
switchConfirmButton: "Yes, switch",
|
|
201
|
+
switchConfirmDismiss: "Never mind",
|
|
197
202
|
noPlans: "No other plans are available right now.",
|
|
198
203
|
notOnInterval: "Not available on this interval",
|
|
199
204
|
loadFailed: "Could not load your plan right now.",
|
|
@@ -981,6 +986,63 @@ function useChangePlan() {
|
|
|
981
986
|
);
|
|
982
987
|
return { changePlan, isChanging };
|
|
983
988
|
}
|
|
989
|
+
function usePlanSwitch(subscription, refetchSubscription, options) {
|
|
990
|
+
const { openCheckout } = useCheckout();
|
|
991
|
+
const { changePlan } = useChangePlan();
|
|
992
|
+
const [pending, setPending] = _react.useState.call(void 0, null);
|
|
993
|
+
const [switching, setSwitching] = _react.useState.call(void 0, false);
|
|
994
|
+
const [switchError, setSwitchError] = _react.useState.call(void 0, null);
|
|
995
|
+
const [checkoutPriceId, setCheckoutPriceId] = _react.useState.call(void 0, null);
|
|
996
|
+
const [checkoutError, setCheckoutError] = _react.useState.call(void 0, null);
|
|
997
|
+
const successUrl = _optionalChain([options, 'optionalAccess', _23 => _23.successUrl]);
|
|
998
|
+
const cancelUrl = _optionalChain([options, 'optionalAccess', _24 => _24.cancelUrl]);
|
|
999
|
+
const selectPlan = _react.useCallback.call(void 0,
|
|
1000
|
+
async (plan, price) => {
|
|
1001
|
+
if (subscription) {
|
|
1002
|
+
setSwitchError(null);
|
|
1003
|
+
setPending({ plan, price });
|
|
1004
|
+
return;
|
|
1005
|
+
}
|
|
1006
|
+
setCheckoutError(null);
|
|
1007
|
+
setCheckoutPriceId(price.id);
|
|
1008
|
+
try {
|
|
1009
|
+
await openCheckout(price.id, { successUrl, cancelUrl });
|
|
1010
|
+
} catch (e) {
|
|
1011
|
+
setCheckoutError(e);
|
|
1012
|
+
setCheckoutPriceId(null);
|
|
1013
|
+
}
|
|
1014
|
+
},
|
|
1015
|
+
[subscription, openCheckout, successUrl, cancelUrl]
|
|
1016
|
+
);
|
|
1017
|
+
const confirmSwitch = _react.useCallback.call(void 0, async () => {
|
|
1018
|
+
if (!pending || !subscription) return;
|
|
1019
|
+
setSwitching(true);
|
|
1020
|
+
setSwitchError(null);
|
|
1021
|
+
try {
|
|
1022
|
+
await changePlan(subscription.id, pending.price.id);
|
|
1023
|
+
setPending(null);
|
|
1024
|
+
refetchSubscription();
|
|
1025
|
+
} catch (e) {
|
|
1026
|
+
setSwitchError(e);
|
|
1027
|
+
} finally {
|
|
1028
|
+
setSwitching(false);
|
|
1029
|
+
}
|
|
1030
|
+
}, [pending, subscription, changePlan, refetchSubscription]);
|
|
1031
|
+
const dismissSwitch = _react.useCallback.call(void 0, () => {
|
|
1032
|
+
setPending(null);
|
|
1033
|
+
setSwitchError(null);
|
|
1034
|
+
}, []);
|
|
1035
|
+
return {
|
|
1036
|
+
pending,
|
|
1037
|
+
switching,
|
|
1038
|
+
switchError,
|
|
1039
|
+
checkoutPriceId,
|
|
1040
|
+
checkoutError,
|
|
1041
|
+
selectPlan,
|
|
1042
|
+
confirmSwitch,
|
|
1043
|
+
dismissSwitch
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
984
1046
|
function useAccess(featureKey, requested) {
|
|
985
1047
|
const client = useClient();
|
|
986
1048
|
const [state, setState] = _react.useState.call(void 0, {
|
|
@@ -1040,8 +1102,8 @@ function useSubscription(productSlug) {
|
|
|
1040
1102
|
setState((prev) => ({ ...prev, isLoading: true }));
|
|
1041
1103
|
fetchOnce({ current: true });
|
|
1042
1104
|
}, [fetchOnce]);
|
|
1043
|
-
const isActive = _optionalChain([state, 'access',
|
|
1044
|
-
const planSlug = _optionalChain([state, 'access',
|
|
1105
|
+
const isActive = _optionalChain([state, 'access', _25 => _25.subscription, 'optionalAccess', _26 => _26.status]) === "ACTIVE" || _optionalChain([state, 'access', _27 => _27.subscription, 'optionalAccess', _28 => _28.status]) === "TRIALING";
|
|
1106
|
+
const planSlug = _optionalChain([state, 'access', _29 => _29.subscription, 'optionalAccess', _30 => _30.plan, 'optionalAccess', _31 => _31.slug]);
|
|
1045
1107
|
return {
|
|
1046
1108
|
...state,
|
|
1047
1109
|
isActive,
|
|
@@ -1189,9 +1251,9 @@ function useUser() {
|
|
|
1189
1251
|
update: updateProfile,
|
|
1190
1252
|
// Computed properties
|
|
1191
1253
|
fullName: user ? `${user.first_name || ""} ${user.last_name || ""}`.trim() : null,
|
|
1192
|
-
initials: user ? `${_optionalChain([user, 'access',
|
|
1193
|
-
email: _optionalChain([user, 'optionalAccess',
|
|
1194
|
-
emailVerified: _optionalChain([user, 'optionalAccess',
|
|
1254
|
+
initials: user ? `${_optionalChain([user, 'access', _32 => _32.first_name, 'optionalAccess', _33 => _33[0]]) || ""}${_optionalChain([user, 'access', _34 => _34.last_name, 'optionalAccess', _35 => _35[0]]) || ""}`.toUpperCase() : null,
|
|
1255
|
+
email: _optionalChain([user, 'optionalAccess', _36 => _36.email]) || null,
|
|
1256
|
+
emailVerified: _optionalChain([user, 'optionalAccess', _37 => _37.email_verified]) || false
|
|
1195
1257
|
};
|
|
1196
1258
|
}
|
|
1197
1259
|
|
|
@@ -1219,4 +1281,5 @@ function useUser() {
|
|
|
1219
1281
|
|
|
1220
1282
|
|
|
1221
1283
|
|
|
1222
|
-
|
|
1284
|
+
|
|
1285
|
+
exports.defaultLocalization = defaultLocalization; exports.useLocalization = useLocalization; exports.fill = fill; exports.fillNode = fillNode; exports.useErrorResolver = useErrorResolver; exports.KerneClient = KerneClient; exports.KerneContext = KerneContext; exports.KerneProvider = KerneProvider; exports.useClient = useClient; exports.useAuth = useAuth; exports.useCheckout = useCheckout; exports.usePortal = usePortal; exports.useCancelSubscription = useCancelSubscription; exports.useChangePlan = useChangePlan; exports.usePlanSwitch = usePlanSwitch; exports.useAccess = useAccess; exports.useSubscription = useSubscription; exports.usePlans = usePlans; exports.useAuthConfig = useAuthConfig; exports.useEntitlements = useEntitlements; exports.useUsage = useUsage; exports.useWaitlist = useWaitlist; exports.useInvitation = useInvitation; exports.useUser = useUser;
|
|
@@ -195,6 +195,11 @@ interface KerneLocalization {
|
|
|
195
195
|
changePlan: string;
|
|
196
196
|
current: string;
|
|
197
197
|
switchTo: string;
|
|
198
|
+
switching: string;
|
|
199
|
+
switchConfirmTitle: string;
|
|
200
|
+
switchConfirmBody: string;
|
|
201
|
+
switchConfirmButton: string;
|
|
202
|
+
switchConfirmDismiss: string;
|
|
198
203
|
noPlans: string;
|
|
199
204
|
notOnInterval: string;
|
|
200
205
|
loadFailed: string;
|
|
@@ -195,6 +195,11 @@ interface KerneLocalization {
|
|
|
195
195
|
changePlan: string;
|
|
196
196
|
current: string;
|
|
197
197
|
switchTo: string;
|
|
198
|
+
switching: string;
|
|
199
|
+
switchConfirmTitle: string;
|
|
200
|
+
switchConfirmBody: string;
|
|
201
|
+
switchConfirmButton: string;
|
|
202
|
+
switchConfirmDismiss: string;
|
|
198
203
|
noPlans: string;
|
|
199
204
|
notOnInterval: string;
|
|
200
205
|
loadFailed: string;
|
package/dist/index.cjs
CHANGED
|
@@ -19,25 +19,26 @@
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
|
|
23
|
+
var _chunkTYNZ2WU7cjs = require('./chunk-TYNZ2WU7.cjs');
|
|
23
24
|
|
|
24
25
|
// src/components.tsx
|
|
25
26
|
var _react = require('react'); var _react2 = _interopRequireDefault(_react);
|
|
26
27
|
var _jsxruntime = require('react/jsx-runtime');
|
|
27
28
|
function Authenticated({ children, fallback = null }) {
|
|
28
|
-
const { isAuthenticated } =
|
|
29
|
+
const { isAuthenticated } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
29
30
|
return isAuthenticated ? children : fallback;
|
|
30
31
|
}
|
|
31
32
|
function Unauthenticated({ children, fallback = null }) {
|
|
32
|
-
const { isAuthenticated } =
|
|
33
|
+
const { isAuthenticated } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
33
34
|
return !isAuthenticated ? children : fallback;
|
|
34
35
|
}
|
|
35
36
|
function AuthLoading({ children }) {
|
|
36
|
-
const client =
|
|
37
|
+
const client = _chunkTYNZ2WU7cjs.useClient.call(void 0, );
|
|
37
38
|
return client.isLoading ? children : null;
|
|
38
39
|
}
|
|
39
40
|
function HasSubscription({ children, fallback = null }) {
|
|
40
|
-
const client =
|
|
41
|
+
const client = _chunkTYNZ2WU7cjs.useClient.call(void 0, );
|
|
41
42
|
const [hasSubscription, setHasSubscription] = _react2.default.useState(null);
|
|
42
43
|
_react2.default.useEffect(() => {
|
|
43
44
|
client.getSubscription().then((sub) => {
|
|
@@ -55,7 +56,7 @@ function Access({
|
|
|
55
56
|
requested,
|
|
56
57
|
fallback = null
|
|
57
58
|
}) {
|
|
58
|
-
const { allowed, isLoading } =
|
|
59
|
+
const { allowed, isLoading } = _chunkTYNZ2WU7cjs.useAccess.call(void 0, featureKey, requested);
|
|
59
60
|
if (isLoading) return null;
|
|
60
61
|
return allowed ? children : fallback;
|
|
61
62
|
}
|
|
@@ -66,7 +67,7 @@ function Protected({
|
|
|
66
67
|
authFallback = null,
|
|
67
68
|
billingFallback = null
|
|
68
69
|
}) {
|
|
69
|
-
const { isAuthenticated } =
|
|
70
|
+
const { isAuthenticated } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
70
71
|
if (auth && !isAuthenticated) {
|
|
71
72
|
return authFallback;
|
|
72
73
|
}
|
|
@@ -179,4 +180,5 @@ function useKerneError() {
|
|
|
179
180
|
|
|
180
181
|
|
|
181
182
|
|
|
182
|
-
|
|
183
|
+
|
|
184
|
+
exports.Access = Access; exports.AuthLoading = AuthLoading; exports.Authenticated = Authenticated; exports.HasSubscription = HasSubscription; exports.KerneClient = _chunkTYNZ2WU7cjs.KerneClient; exports.KerneContext = _chunkTYNZ2WU7cjs.KerneContext; exports.KerneErrorBoundary = KerneErrorBoundary; exports.KerneProvider = _chunkTYNZ2WU7cjs.KerneProvider; exports.Protected = Protected; exports.Unauthenticated = Unauthenticated; exports.defaultLocalization = _chunkTYNZ2WU7cjs.defaultLocalization; exports.useAccess = _chunkTYNZ2WU7cjs.useAccess; exports.useAuth = _chunkTYNZ2WU7cjs.useAuth; exports.useAuthConfig = _chunkTYNZ2WU7cjs.useAuthConfig; exports.useCancelSubscription = _chunkTYNZ2WU7cjs.useCancelSubscription; exports.useChangePlan = _chunkTYNZ2WU7cjs.useChangePlan; exports.useCheckout = _chunkTYNZ2WU7cjs.useCheckout; exports.useClient = _chunkTYNZ2WU7cjs.useClient; exports.useEntitlements = _chunkTYNZ2WU7cjs.useEntitlements; exports.useInvitation = _chunkTYNZ2WU7cjs.useInvitation; exports.useKerneError = useKerneError; exports.usePlanSwitch = _chunkTYNZ2WU7cjs.usePlanSwitch; exports.usePlans = _chunkTYNZ2WU7cjs.usePlans; exports.usePortal = _chunkTYNZ2WU7cjs.usePortal; exports.useSubscription = _chunkTYNZ2WU7cjs.useSubscription; exports.useUsage = _chunkTYNZ2WU7cjs.useUsage; exports.useUser = _chunkTYNZ2WU7cjs.useUser; exports.useWaitlist = _chunkTYNZ2WU7cjs.useWaitlist;
|
package/dist/index.d.cts
CHANGED
|
@@ -3,10 +3,10 @@ import React, { ReactNode, Component, ErrorInfo } from 'react';
|
|
|
3
3
|
import { KerneConfig, JoinWaitlistParams, ValidateTokenResponse, ValidateCodeResponse } from '@kerne/server';
|
|
4
4
|
export { JoinWaitlistParams, ValidateCodeResponse, ValidateTokenResponse, WaitlistEntry } from '@kerne/server';
|
|
5
5
|
import * as _kerne_types from '@kerne/types';
|
|
6
|
-
import { User, AuthResponse, ActivationContext, AuthConfig, EntitlementCheck, SubscriptionWithPlan, Subscription, PublicPlan, Entitlements, UsageRecord } from '@kerne/types';
|
|
6
|
+
import { User, AuthResponse, ActivationContext, AuthConfig, EntitlementCheck, SubscriptionWithPlan, Subscription, PublicPlan, Entitlements, UsageRecord, PublicPlanPrice } from '@kerne/types';
|
|
7
7
|
export { ActivationContext, AuthConfig, AuthResponse, EntitlementCheck, Entitlements, PublicPlan, Subscription, SubscriptionWithPlan, UsageRecord, User } from '@kerne/types';
|
|
8
|
-
import { D as DeepPartial, K as KerneLocalization } from './i18n-
|
|
9
|
-
export { d as defaultLocalization } from './i18n-
|
|
8
|
+
import { D as DeepPartial, K as KerneLocalization } from './i18n-QilNgwqe.cjs';
|
|
9
|
+
export { d as defaultLocalization } from './i18n-QilNgwqe.cjs';
|
|
10
10
|
|
|
11
11
|
interface KerneReactConfig extends Omit<KerneConfig, 'secretKey'> {
|
|
12
12
|
storage?: Storage;
|
|
@@ -344,6 +344,51 @@ declare function useChangePlan(): {
|
|
|
344
344
|
}) => Promise<SubscriptionWithPlan>;
|
|
345
345
|
isChanging: boolean;
|
|
346
346
|
};
|
|
347
|
+
interface PlanSwitchTarget {
|
|
348
|
+
plan: PublicPlan;
|
|
349
|
+
price: PublicPlanPrice;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* The decision every "pick a plan" surface needs, shared so it is only
|
|
353
|
+
* decided once: an existing subscriber switching plans has to swap in place
|
|
354
|
+
* (`changePlanPrice`), never start a fresh checkout - Stripe/Polar don't know
|
|
355
|
+
* about the subscription already on file, so a new checkout session creates
|
|
356
|
+
* a SECOND, independent one instead of replacing it. The old one stays live
|
|
357
|
+
* and billed at the provider while Kerne only ever tracks the new one. A
|
|
358
|
+
* first-time subscriber has nothing to swap, so that case goes straight to
|
|
359
|
+
* checkout, same as before.
|
|
360
|
+
*
|
|
361
|
+
* The switch is staged rather than applied on `selectPlan` alone - it bills
|
|
362
|
+
* immediately on confirmation (unlike checkout, which only starts billing
|
|
363
|
+
* once the provider's own page is completed), so the caller's UI gets a
|
|
364
|
+
* chance to say so before `confirmSwitch()` commits it.
|
|
365
|
+
*
|
|
366
|
+
* @param subscription the subject's current subscription, or null - pass
|
|
367
|
+
* what `useSubscription()` already returned rather than fetching it again
|
|
368
|
+
* here, so a page showing the current plan and this hook always agree.
|
|
369
|
+
* @param refetchSubscription called after a successful switch, typically
|
|
370
|
+
* that same `useSubscription()` call's own `refetch()`.
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* ```tsx
|
|
374
|
+
* const { subscription, refetch } = useSubscription();
|
|
375
|
+
* const { pending, switching, selectPlan, confirmSwitch, dismissSwitch } =
|
|
376
|
+
* usePlanSwitch(subscription, refetch);
|
|
377
|
+
* ```
|
|
378
|
+
*/
|
|
379
|
+
declare function usePlanSwitch(subscription: SubscriptionWithPlan | null, refetchSubscription: () => void, options?: {
|
|
380
|
+
successUrl?: string;
|
|
381
|
+
cancelUrl?: string;
|
|
382
|
+
}): {
|
|
383
|
+
pending: PlanSwitchTarget | null;
|
|
384
|
+
switching: boolean;
|
|
385
|
+
switchError: unknown;
|
|
386
|
+
checkoutPriceId: string | null;
|
|
387
|
+
checkoutError: unknown;
|
|
388
|
+
selectPlan: (plan: PublicPlan, price: PublicPlanPrice) => Promise<void>;
|
|
389
|
+
confirmSwitch: () => Promise<void>;
|
|
390
|
+
dismissSwitch: () => void;
|
|
391
|
+
};
|
|
347
392
|
/**
|
|
348
393
|
* Whether the current scope has access to one feature - the single entry
|
|
349
394
|
* point for a live, per-feature decision. Deliberately not named after what
|
|
@@ -691,4 +736,4 @@ declare function useKerneError(): {
|
|
|
691
736
|
clearError: () => void;
|
|
692
737
|
};
|
|
693
738
|
|
|
694
|
-
export { Access, AuthLoading, Authenticated, HasSubscription, KerneClient, KerneContext, type KerneError, KerneErrorBoundary, KerneLocalization, KerneProvider, type KerneProviderProps, type KerneReactConfig, Protected, Unauthenticated, useAccess, useAuth, useAuthConfig, useCancelSubscription, useChangePlan, useCheckout, useClient, useEntitlements, useInvitation, useKerneError, usePlans, usePortal, useSubscription, useUsage, useUser, useWaitlist };
|
|
739
|
+
export { Access, AuthLoading, Authenticated, HasSubscription, KerneClient, KerneContext, type KerneError, KerneErrorBoundary, KerneLocalization, KerneProvider, type KerneProviderProps, type KerneReactConfig, type PlanSwitchTarget, Protected, Unauthenticated, useAccess, useAuth, useAuthConfig, useCancelSubscription, useChangePlan, useCheckout, useClient, useEntitlements, useInvitation, useKerneError, usePlanSwitch, usePlans, usePortal, useSubscription, useUsage, useUser, useWaitlist };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,10 +3,10 @@ import React, { ReactNode, Component, ErrorInfo } from 'react';
|
|
|
3
3
|
import { KerneConfig, JoinWaitlistParams, ValidateTokenResponse, ValidateCodeResponse } from '@kerne/server';
|
|
4
4
|
export { JoinWaitlistParams, ValidateCodeResponse, ValidateTokenResponse, WaitlistEntry } from '@kerne/server';
|
|
5
5
|
import * as _kerne_types from '@kerne/types';
|
|
6
|
-
import { User, AuthResponse, ActivationContext, AuthConfig, EntitlementCheck, SubscriptionWithPlan, Subscription, PublicPlan, Entitlements, UsageRecord } from '@kerne/types';
|
|
6
|
+
import { User, AuthResponse, ActivationContext, AuthConfig, EntitlementCheck, SubscriptionWithPlan, Subscription, PublicPlan, Entitlements, UsageRecord, PublicPlanPrice } from '@kerne/types';
|
|
7
7
|
export { ActivationContext, AuthConfig, AuthResponse, EntitlementCheck, Entitlements, PublicPlan, Subscription, SubscriptionWithPlan, UsageRecord, User } from '@kerne/types';
|
|
8
|
-
import { D as DeepPartial, K as KerneLocalization } from './i18n-
|
|
9
|
-
export { d as defaultLocalization } from './i18n-
|
|
8
|
+
import { D as DeepPartial, K as KerneLocalization } from './i18n-QilNgwqe.js';
|
|
9
|
+
export { d as defaultLocalization } from './i18n-QilNgwqe.js';
|
|
10
10
|
|
|
11
11
|
interface KerneReactConfig extends Omit<KerneConfig, 'secretKey'> {
|
|
12
12
|
storage?: Storage;
|
|
@@ -344,6 +344,51 @@ declare function useChangePlan(): {
|
|
|
344
344
|
}) => Promise<SubscriptionWithPlan>;
|
|
345
345
|
isChanging: boolean;
|
|
346
346
|
};
|
|
347
|
+
interface PlanSwitchTarget {
|
|
348
|
+
plan: PublicPlan;
|
|
349
|
+
price: PublicPlanPrice;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* The decision every "pick a plan" surface needs, shared so it is only
|
|
353
|
+
* decided once: an existing subscriber switching plans has to swap in place
|
|
354
|
+
* (`changePlanPrice`), never start a fresh checkout - Stripe/Polar don't know
|
|
355
|
+
* about the subscription already on file, so a new checkout session creates
|
|
356
|
+
* a SECOND, independent one instead of replacing it. The old one stays live
|
|
357
|
+
* and billed at the provider while Kerne only ever tracks the new one. A
|
|
358
|
+
* first-time subscriber has nothing to swap, so that case goes straight to
|
|
359
|
+
* checkout, same as before.
|
|
360
|
+
*
|
|
361
|
+
* The switch is staged rather than applied on `selectPlan` alone - it bills
|
|
362
|
+
* immediately on confirmation (unlike checkout, which only starts billing
|
|
363
|
+
* once the provider's own page is completed), so the caller's UI gets a
|
|
364
|
+
* chance to say so before `confirmSwitch()` commits it.
|
|
365
|
+
*
|
|
366
|
+
* @param subscription the subject's current subscription, or null - pass
|
|
367
|
+
* what `useSubscription()` already returned rather than fetching it again
|
|
368
|
+
* here, so a page showing the current plan and this hook always agree.
|
|
369
|
+
* @param refetchSubscription called after a successful switch, typically
|
|
370
|
+
* that same `useSubscription()` call's own `refetch()`.
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* ```tsx
|
|
374
|
+
* const { subscription, refetch } = useSubscription();
|
|
375
|
+
* const { pending, switching, selectPlan, confirmSwitch, dismissSwitch } =
|
|
376
|
+
* usePlanSwitch(subscription, refetch);
|
|
377
|
+
* ```
|
|
378
|
+
*/
|
|
379
|
+
declare function usePlanSwitch(subscription: SubscriptionWithPlan | null, refetchSubscription: () => void, options?: {
|
|
380
|
+
successUrl?: string;
|
|
381
|
+
cancelUrl?: string;
|
|
382
|
+
}): {
|
|
383
|
+
pending: PlanSwitchTarget | null;
|
|
384
|
+
switching: boolean;
|
|
385
|
+
switchError: unknown;
|
|
386
|
+
checkoutPriceId: string | null;
|
|
387
|
+
checkoutError: unknown;
|
|
388
|
+
selectPlan: (plan: PublicPlan, price: PublicPlanPrice) => Promise<void>;
|
|
389
|
+
confirmSwitch: () => Promise<void>;
|
|
390
|
+
dismissSwitch: () => void;
|
|
391
|
+
};
|
|
347
392
|
/**
|
|
348
393
|
* Whether the current scope has access to one feature - the single entry
|
|
349
394
|
* point for a live, per-feature decision. Deliberately not named after what
|
|
@@ -691,4 +736,4 @@ declare function useKerneError(): {
|
|
|
691
736
|
clearError: () => void;
|
|
692
737
|
};
|
|
693
738
|
|
|
694
|
-
export { Access, AuthLoading, Authenticated, HasSubscription, KerneClient, KerneContext, type KerneError, KerneErrorBoundary, KerneLocalization, KerneProvider, type KerneProviderProps, type KerneReactConfig, Protected, Unauthenticated, useAccess, useAuth, useAuthConfig, useCancelSubscription, useChangePlan, useCheckout, useClient, useEntitlements, useInvitation, useKerneError, usePlans, usePortal, useSubscription, useUsage, useUser, useWaitlist };
|
|
739
|
+
export { Access, AuthLoading, Authenticated, HasSubscription, KerneClient, KerneContext, type KerneError, KerneErrorBoundary, KerneLocalization, KerneProvider, type KerneProviderProps, type KerneReactConfig, type PlanSwitchTarget, Protected, Unauthenticated, useAccess, useAuth, useAuthConfig, useCancelSubscription, useChangePlan, useCheckout, useClient, useEntitlements, useInvitation, useKerneError, usePlanSwitch, usePlans, usePortal, useSubscription, useUsage, useUser, useWaitlist };
|
package/dist/index.js
CHANGED
|
@@ -13,13 +13,14 @@ import {
|
|
|
13
13
|
useClient,
|
|
14
14
|
useEntitlements,
|
|
15
15
|
useInvitation,
|
|
16
|
+
usePlanSwitch,
|
|
16
17
|
usePlans,
|
|
17
18
|
usePortal,
|
|
18
19
|
useSubscription,
|
|
19
20
|
useUsage,
|
|
20
21
|
useUser,
|
|
21
22
|
useWaitlist
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-IZMRK3WK.js";
|
|
23
24
|
|
|
24
25
|
// src/components.tsx
|
|
25
26
|
import React from "react";
|
|
@@ -173,6 +174,7 @@ export {
|
|
|
173
174
|
useEntitlements,
|
|
174
175
|
useInvitation,
|
|
175
176
|
useKerneError,
|
|
177
|
+
usePlanSwitch,
|
|
176
178
|
usePlans,
|
|
177
179
|
usePortal,
|
|
178
180
|
useSubscription,
|