@kerne/react 0.1.3 → 1.0.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/README.md +18 -5
- package/dist/{chunk-7U3QBMA7.cjs → chunk-IMZFZ3P5.cjs} +88 -17
- package/dist/{chunk-F6NV76OR.js → chunk-NFJ2S5VJ.js} +87 -16
- package/dist/{i18n-BWTT1DWD.d.cts → i18n-Di5qlnL1.d.cts} +28 -0
- package/dist/{i18n-BWTT1DWD.d.ts → i18n-Di5qlnL1.d.ts} +28 -0
- package/dist/index.cjs +16 -20
- package/dist/index.d.cts +52 -13
- package/dist/index.d.ts +52 -13
- package/dist/index.js +11 -15
- package/dist/ui/index.cjs +624 -112
- package/dist/ui/index.d.cts +67 -4
- package/dist/ui/index.d.ts +67 -4
- package/dist/ui/index.js +556 -44
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -44,20 +44,32 @@ function LoginForm() {
|
|
|
44
44
|
|
|
45
45
|
## Gating a feature
|
|
46
46
|
|
|
47
|
-
`
|
|
47
|
+
`Access` (and the underlying `useAccess` hook) check the logged-in user automatically - no scope to pass, the SDK already knows who's authenticated.
|
|
48
48
|
|
|
49
49
|
```tsx
|
|
50
|
-
import {
|
|
50
|
+
import { Access } from '@kerne/react';
|
|
51
51
|
|
|
52
52
|
function ExportButton() {
|
|
53
53
|
return (
|
|
54
|
-
<
|
|
54
|
+
<Access featureKey="export_pdf" fallback={<UpgradePrompt />}>
|
|
55
55
|
<button onClick={exportPdf}>Export as PDF</button>
|
|
56
|
-
</
|
|
56
|
+
</Access>
|
|
57
57
|
);
|
|
58
58
|
}
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
+
Pass `requested` to check a quantity before it's spent, not after - useful right before a batch action:
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
<Access
|
|
65
|
+
featureKey="ai_credits"
|
|
66
|
+
requested={5}
|
|
67
|
+
fallback={<UpgradePrompt reason="Not enough credits for batch processing" />}
|
|
68
|
+
>
|
|
69
|
+
<BatchProcessButton count={5} />
|
|
70
|
+
</Access>
|
|
71
|
+
```
|
|
72
|
+
|
|
61
73
|
For the full detail behind a check (limit/used/remaining, not just a boolean), read `details` from the same hook - `const { allowed, details } = useAccess('api_calls')`.
|
|
62
74
|
|
|
63
75
|
## Checkout & billing portal
|
|
@@ -75,8 +87,9 @@ const { openPortal } = usePortal();
|
|
|
75
87
|
- `useUser`: the current authenticated user's profile.
|
|
76
88
|
- `useAccess`: feature access - `allowed` for the go/no-go, `details` for limit/used/remaining.
|
|
77
89
|
- `useUsage`, `useEntitlements`: usage and full entitlement lists for the current user.
|
|
78
|
-
- `useSubscription`, `usePlans`: the current subscription and the tenant's public plan catalog.
|
|
90
|
+
- `useSubscription`, `usePlans`: the current subscription (with `refetch`) and the tenant's public plan catalog.
|
|
79
91
|
- `useCheckout`, `usePortal`: hosted checkout and billing-portal sessions.
|
|
92
|
+
- `useCancelSubscription`, `useChangePlan`: cancel or switch plan. Both act on the payment provider first, then on Kerne, so a cancellation really stops the next invoice.
|
|
80
93
|
|
|
81
94
|
## Documentation
|
|
82
95
|
|
|
@@ -185,6 +185,12 @@ var defaultLocalization = {
|
|
|
185
185
|
freePlan: "You are on the free plan.",
|
|
186
186
|
seePlans: "See plans",
|
|
187
187
|
cancelNotice: "Your plan is set to end - you keep access until the date above.",
|
|
188
|
+
cancelSubscription: "Cancel subscription",
|
|
189
|
+
canceling: "Canceling...",
|
|
190
|
+
cancelConfirmTitle: "Cancel your subscription?",
|
|
191
|
+
cancelConfirmBody: "You'll keep access until the end of the current billing period.",
|
|
192
|
+
cancelConfirmButton: "Yes, cancel",
|
|
193
|
+
cancelConfirmDismiss: "Never mind",
|
|
188
194
|
changePlan: "Change plan",
|
|
189
195
|
current: "Current",
|
|
190
196
|
switchTo: "Switch",
|
|
@@ -212,11 +218,23 @@ var defaultLocalization = {
|
|
|
212
218
|
subtitle: "Counted against your plan for the current period.",
|
|
213
219
|
used: "{count} used",
|
|
214
220
|
nothingMetered: "Nothing metered on your plan - you have no usage limits to watch.",
|
|
215
|
-
overage: "{count} over your included amount -
|
|
221
|
+
overage: "{count} over your included amount - at no extra charge.",
|
|
222
|
+
overageBilled: "{count} over your included amount - the extra is billed on top of your plan.",
|
|
216
223
|
limitReached: "You have reached your limit.",
|
|
224
|
+
capReached: "You've reached your billing cap for this period - everything past this is free.",
|
|
225
|
+
billedAmount: "{amount} billed this period.",
|
|
217
226
|
loading: "Loading usage",
|
|
218
227
|
loadFailed: "Could not load your usage right now."
|
|
219
228
|
},
|
|
229
|
+
pricing: {
|
|
230
|
+
getStarted: "Get started",
|
|
231
|
+
billedAt: "Billed {amount} / {interval}",
|
|
232
|
+
save: "Save {percent}%",
|
|
233
|
+
unlimited: "Unlimited",
|
|
234
|
+
moreFeatures: "+{count} more",
|
|
235
|
+
loading: "Loading plans",
|
|
236
|
+
loadFailed: "Could not load plans right now."
|
|
237
|
+
},
|
|
220
238
|
checkout: {
|
|
221
239
|
confirmingTitle: "Confirming your payment",
|
|
222
240
|
confirmingBody: "This takes a few seconds - please keep this tab open.",
|
|
@@ -714,7 +732,7 @@ var KerneClient = (_class = class {
|
|
|
714
732
|
* caught everything and returned `false`) - a 401/500 must not be
|
|
715
733
|
* indistinguishable from a real denial, that's exactly what let the
|
|
716
734
|
* `has_access`/`allowed` mismatch below ship unnoticed. Callers that want
|
|
717
|
-
* a fail-closed boolean regardless of the reason (e.g. `<
|
|
735
|
+
* a fail-closed boolean regardless of the reason (e.g. `<Access>`)
|
|
718
736
|
* catch around this themselves.
|
|
719
737
|
*/
|
|
720
738
|
async allows(featureKey, requested) {
|
|
@@ -744,13 +762,21 @@ var KerneClient = (_class = class {
|
|
|
744
762
|
async getSubscription(productSlug) {
|
|
745
763
|
const subs = await this.kerne.billing.subscriptions.list({
|
|
746
764
|
productSlug,
|
|
747
|
-
|
|
765
|
+
subjectType: "USER"
|
|
748
766
|
});
|
|
749
767
|
const active = subs.find(
|
|
750
768
|
(s) => s.status === "ACTIVE" || s.status === "TRIALING" || s.status === "PAST_DUE"
|
|
751
769
|
);
|
|
752
770
|
return _nullishCoalesce(active, () => ( null));
|
|
753
771
|
}
|
|
772
|
+
/** `immediately: true` ends it now; otherwise cancels at period end (API default). */
|
|
773
|
+
async cancelSubscription(subscriptionId, immediately) {
|
|
774
|
+
return this.kerne.billing.subscriptions.cancel(subscriptionId, immediately);
|
|
775
|
+
}
|
|
776
|
+
/** Swaps the plan/price, effective immediately - deferring a downgrade isn't supported yet. */
|
|
777
|
+
async changeSubscriptionPlan(subscriptionId, planPriceId, options) {
|
|
778
|
+
return this.kerne.billing.subscriptions.changePlanPrice(subscriptionId, planPriceId, options);
|
|
779
|
+
}
|
|
754
780
|
/** Public pricing data - omit `productIdOrSlug` for the tenant's default product. */
|
|
755
781
|
async getPlans(productIdOrSlug) {
|
|
756
782
|
return this.kerne.billing.plans(productIdOrSlug);
|
|
@@ -923,6 +949,38 @@ function usePortal() {
|
|
|
923
949
|
openPortal: _react.useCallback.call(void 0, (returnUrl) => client.openPortal(returnUrl), [client])
|
|
924
950
|
};
|
|
925
951
|
}
|
|
952
|
+
function useCancelSubscription() {
|
|
953
|
+
const client = useClient();
|
|
954
|
+
const [isCanceling, setIsCanceling] = _react.useState.call(void 0, false);
|
|
955
|
+
const cancelSubscription = _react.useCallback.call(void 0,
|
|
956
|
+
async (subscriptionId, immediately) => {
|
|
957
|
+
setIsCanceling(true);
|
|
958
|
+
try {
|
|
959
|
+
return await client.cancelSubscription(subscriptionId, immediately);
|
|
960
|
+
} finally {
|
|
961
|
+
setIsCanceling(false);
|
|
962
|
+
}
|
|
963
|
+
},
|
|
964
|
+
[client]
|
|
965
|
+
);
|
|
966
|
+
return { cancelSubscription, isCanceling };
|
|
967
|
+
}
|
|
968
|
+
function useChangePlan() {
|
|
969
|
+
const client = useClient();
|
|
970
|
+
const [isChanging, setIsChanging] = _react.useState.call(void 0, false);
|
|
971
|
+
const changePlan = _react.useCallback.call(void 0,
|
|
972
|
+
async (subscriptionId, planPriceId, options) => {
|
|
973
|
+
setIsChanging(true);
|
|
974
|
+
try {
|
|
975
|
+
return await client.changeSubscriptionPlan(subscriptionId, planPriceId, options);
|
|
976
|
+
} finally {
|
|
977
|
+
setIsChanging(false);
|
|
978
|
+
}
|
|
979
|
+
},
|
|
980
|
+
[client]
|
|
981
|
+
);
|
|
982
|
+
return { changePlan, isChanging };
|
|
983
|
+
}
|
|
926
984
|
function useAccess(featureKey, requested) {
|
|
927
985
|
const client = useClient();
|
|
928
986
|
const [state, setState] = _react.useState.call(void 0, {
|
|
@@ -957,27 +1015,38 @@ function useSubscription(productSlug) {
|
|
|
957
1015
|
isLoading: true,
|
|
958
1016
|
error: null
|
|
959
1017
|
});
|
|
1018
|
+
const fetchOnce = _react.useCallback.call(void 0,
|
|
1019
|
+
(mountedRef) => {
|
|
1020
|
+
client.getSubscription(productSlug).then((subscription) => {
|
|
1021
|
+
if (mountedRef.current) {
|
|
1022
|
+
setState({ subscription, isLoading: false, error: null });
|
|
1023
|
+
}
|
|
1024
|
+
}).catch((error) => {
|
|
1025
|
+
if (mountedRef.current) {
|
|
1026
|
+
setState({ subscription: null, isLoading: false, error });
|
|
1027
|
+
}
|
|
1028
|
+
});
|
|
1029
|
+
},
|
|
1030
|
+
[client, productSlug]
|
|
1031
|
+
);
|
|
960
1032
|
_react.useEffect.call(void 0, () => {
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
if (mounted) {
|
|
964
|
-
setState({ subscription, isLoading: false, error: null });
|
|
965
|
-
}
|
|
966
|
-
}).catch((error) => {
|
|
967
|
-
if (mounted) {
|
|
968
|
-
setState({ subscription: null, isLoading: false, error });
|
|
969
|
-
}
|
|
970
|
-
});
|
|
1033
|
+
const mountedRef = { current: true };
|
|
1034
|
+
fetchOnce(mountedRef);
|
|
971
1035
|
return () => {
|
|
972
|
-
|
|
1036
|
+
mountedRef.current = false;
|
|
973
1037
|
};
|
|
974
|
-
}, [
|
|
1038
|
+
}, [fetchOnce]);
|
|
1039
|
+
const refetch = _react.useCallback.call(void 0, () => {
|
|
1040
|
+
setState((prev) => ({ ...prev, isLoading: true }));
|
|
1041
|
+
fetchOnce({ current: true });
|
|
1042
|
+
}, [fetchOnce]);
|
|
975
1043
|
const isActive = _optionalChain([state, 'access', _23 => _23.subscription, 'optionalAccess', _24 => _24.status]) === "ACTIVE" || _optionalChain([state, 'access', _25 => _25.subscription, 'optionalAccess', _26 => _26.status]) === "TRIALING";
|
|
976
1044
|
const planSlug = _optionalChain([state, 'access', _27 => _27.subscription, 'optionalAccess', _28 => _28.plan, 'optionalAccess', _29 => _29.slug]);
|
|
977
1045
|
return {
|
|
978
1046
|
...state,
|
|
979
1047
|
isActive,
|
|
980
|
-
planSlug
|
|
1048
|
+
planSlug,
|
|
1049
|
+
refetch
|
|
981
1050
|
};
|
|
982
1051
|
}
|
|
983
1052
|
function usePlans(productIdOrSlug) {
|
|
@@ -1148,4 +1217,6 @@ function useUser() {
|
|
|
1148
1217
|
|
|
1149
1218
|
|
|
1150
1219
|
|
|
1151
|
-
|
|
1220
|
+
|
|
1221
|
+
|
|
1222
|
+
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.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;
|
|
@@ -185,6 +185,12 @@ var defaultLocalization = {
|
|
|
185
185
|
freePlan: "You are on the free plan.",
|
|
186
186
|
seePlans: "See plans",
|
|
187
187
|
cancelNotice: "Your plan is set to end - you keep access until the date above.",
|
|
188
|
+
cancelSubscription: "Cancel subscription",
|
|
189
|
+
canceling: "Canceling...",
|
|
190
|
+
cancelConfirmTitle: "Cancel your subscription?",
|
|
191
|
+
cancelConfirmBody: "You'll keep access until the end of the current billing period.",
|
|
192
|
+
cancelConfirmButton: "Yes, cancel",
|
|
193
|
+
cancelConfirmDismiss: "Never mind",
|
|
188
194
|
changePlan: "Change plan",
|
|
189
195
|
current: "Current",
|
|
190
196
|
switchTo: "Switch",
|
|
@@ -212,11 +218,23 @@ var defaultLocalization = {
|
|
|
212
218
|
subtitle: "Counted against your plan for the current period.",
|
|
213
219
|
used: "{count} used",
|
|
214
220
|
nothingMetered: "Nothing metered on your plan - you have no usage limits to watch.",
|
|
215
|
-
overage: "{count} over your included amount -
|
|
221
|
+
overage: "{count} over your included amount - at no extra charge.",
|
|
222
|
+
overageBilled: "{count} over your included amount - the extra is billed on top of your plan.",
|
|
216
223
|
limitReached: "You have reached your limit.",
|
|
224
|
+
capReached: "You've reached your billing cap for this period - everything past this is free.",
|
|
225
|
+
billedAmount: "{amount} billed this period.",
|
|
217
226
|
loading: "Loading usage",
|
|
218
227
|
loadFailed: "Could not load your usage right now."
|
|
219
228
|
},
|
|
229
|
+
pricing: {
|
|
230
|
+
getStarted: "Get started",
|
|
231
|
+
billedAt: "Billed {amount} / {interval}",
|
|
232
|
+
save: "Save {percent}%",
|
|
233
|
+
unlimited: "Unlimited",
|
|
234
|
+
moreFeatures: "+{count} more",
|
|
235
|
+
loading: "Loading plans",
|
|
236
|
+
loadFailed: "Could not load plans right now."
|
|
237
|
+
},
|
|
220
238
|
checkout: {
|
|
221
239
|
confirmingTitle: "Confirming your payment",
|
|
222
240
|
confirmingBody: "This takes a few seconds - please keep this tab open.",
|
|
@@ -714,7 +732,7 @@ var KerneClient = class {
|
|
|
714
732
|
* caught everything and returned `false`) - a 401/500 must not be
|
|
715
733
|
* indistinguishable from a real denial, that's exactly what let the
|
|
716
734
|
* `has_access`/`allowed` mismatch below ship unnoticed. Callers that want
|
|
717
|
-
* a fail-closed boolean regardless of the reason (e.g. `<
|
|
735
|
+
* a fail-closed boolean regardless of the reason (e.g. `<Access>`)
|
|
718
736
|
* catch around this themselves.
|
|
719
737
|
*/
|
|
720
738
|
async allows(featureKey, requested) {
|
|
@@ -744,13 +762,21 @@ var KerneClient = class {
|
|
|
744
762
|
async getSubscription(productSlug) {
|
|
745
763
|
const subs = await this.kerne.billing.subscriptions.list({
|
|
746
764
|
productSlug,
|
|
747
|
-
|
|
765
|
+
subjectType: "USER"
|
|
748
766
|
});
|
|
749
767
|
const active = subs.find(
|
|
750
768
|
(s) => s.status === "ACTIVE" || s.status === "TRIALING" || s.status === "PAST_DUE"
|
|
751
769
|
);
|
|
752
770
|
return active ?? null;
|
|
753
771
|
}
|
|
772
|
+
/** `immediately: true` ends it now; otherwise cancels at period end (API default). */
|
|
773
|
+
async cancelSubscription(subscriptionId, immediately) {
|
|
774
|
+
return this.kerne.billing.subscriptions.cancel(subscriptionId, immediately);
|
|
775
|
+
}
|
|
776
|
+
/** Swaps the plan/price, effective immediately - deferring a downgrade isn't supported yet. */
|
|
777
|
+
async changeSubscriptionPlan(subscriptionId, planPriceId, options) {
|
|
778
|
+
return this.kerne.billing.subscriptions.changePlanPrice(subscriptionId, planPriceId, options);
|
|
779
|
+
}
|
|
754
780
|
/** Public pricing data - omit `productIdOrSlug` for the tenant's default product. */
|
|
755
781
|
async getPlans(productIdOrSlug) {
|
|
756
782
|
return this.kerne.billing.plans(productIdOrSlug);
|
|
@@ -923,6 +949,38 @@ function usePortal() {
|
|
|
923
949
|
openPortal: useCallback2((returnUrl) => client.openPortal(returnUrl), [client])
|
|
924
950
|
};
|
|
925
951
|
}
|
|
952
|
+
function useCancelSubscription() {
|
|
953
|
+
const client = useClient();
|
|
954
|
+
const [isCanceling, setIsCanceling] = useState(false);
|
|
955
|
+
const cancelSubscription = useCallback2(
|
|
956
|
+
async (subscriptionId, immediately) => {
|
|
957
|
+
setIsCanceling(true);
|
|
958
|
+
try {
|
|
959
|
+
return await client.cancelSubscription(subscriptionId, immediately);
|
|
960
|
+
} finally {
|
|
961
|
+
setIsCanceling(false);
|
|
962
|
+
}
|
|
963
|
+
},
|
|
964
|
+
[client]
|
|
965
|
+
);
|
|
966
|
+
return { cancelSubscription, isCanceling };
|
|
967
|
+
}
|
|
968
|
+
function useChangePlan() {
|
|
969
|
+
const client = useClient();
|
|
970
|
+
const [isChanging, setIsChanging] = useState(false);
|
|
971
|
+
const changePlan = useCallback2(
|
|
972
|
+
async (subscriptionId, planPriceId, options) => {
|
|
973
|
+
setIsChanging(true);
|
|
974
|
+
try {
|
|
975
|
+
return await client.changeSubscriptionPlan(subscriptionId, planPriceId, options);
|
|
976
|
+
} finally {
|
|
977
|
+
setIsChanging(false);
|
|
978
|
+
}
|
|
979
|
+
},
|
|
980
|
+
[client]
|
|
981
|
+
);
|
|
982
|
+
return { changePlan, isChanging };
|
|
983
|
+
}
|
|
926
984
|
function useAccess(featureKey, requested) {
|
|
927
985
|
const client = useClient();
|
|
928
986
|
const [state, setState] = useState({
|
|
@@ -957,27 +1015,38 @@ function useSubscription(productSlug) {
|
|
|
957
1015
|
isLoading: true,
|
|
958
1016
|
error: null
|
|
959
1017
|
});
|
|
1018
|
+
const fetchOnce = useCallback2(
|
|
1019
|
+
(mountedRef) => {
|
|
1020
|
+
client.getSubscription(productSlug).then((subscription) => {
|
|
1021
|
+
if (mountedRef.current) {
|
|
1022
|
+
setState({ subscription, isLoading: false, error: null });
|
|
1023
|
+
}
|
|
1024
|
+
}).catch((error) => {
|
|
1025
|
+
if (mountedRef.current) {
|
|
1026
|
+
setState({ subscription: null, isLoading: false, error });
|
|
1027
|
+
}
|
|
1028
|
+
});
|
|
1029
|
+
},
|
|
1030
|
+
[client, productSlug]
|
|
1031
|
+
);
|
|
960
1032
|
useEffect2(() => {
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
if (mounted) {
|
|
964
|
-
setState({ subscription, isLoading: false, error: null });
|
|
965
|
-
}
|
|
966
|
-
}).catch((error) => {
|
|
967
|
-
if (mounted) {
|
|
968
|
-
setState({ subscription: null, isLoading: false, error });
|
|
969
|
-
}
|
|
970
|
-
});
|
|
1033
|
+
const mountedRef = { current: true };
|
|
1034
|
+
fetchOnce(mountedRef);
|
|
971
1035
|
return () => {
|
|
972
|
-
|
|
1036
|
+
mountedRef.current = false;
|
|
973
1037
|
};
|
|
974
|
-
}, [
|
|
1038
|
+
}, [fetchOnce]);
|
|
1039
|
+
const refetch = useCallback2(() => {
|
|
1040
|
+
setState((prev) => ({ ...prev, isLoading: true }));
|
|
1041
|
+
fetchOnce({ current: true });
|
|
1042
|
+
}, [fetchOnce]);
|
|
975
1043
|
const isActive = state.subscription?.status === "ACTIVE" || state.subscription?.status === "TRIALING";
|
|
976
1044
|
const planSlug = state.subscription?.plan?.slug;
|
|
977
1045
|
return {
|
|
978
1046
|
...state,
|
|
979
1047
|
isActive,
|
|
980
|
-
planSlug
|
|
1048
|
+
planSlug,
|
|
1049
|
+
refetch
|
|
981
1050
|
};
|
|
982
1051
|
}
|
|
983
1052
|
function usePlans(productIdOrSlug) {
|
|
@@ -1139,6 +1208,8 @@ export {
|
|
|
1139
1208
|
useAuth,
|
|
1140
1209
|
useCheckout,
|
|
1141
1210
|
usePortal,
|
|
1211
|
+
useCancelSubscription,
|
|
1212
|
+
useChangePlan,
|
|
1142
1213
|
useAccess,
|
|
1143
1214
|
useSubscription,
|
|
1144
1215
|
usePlans,
|
|
@@ -186,6 +186,12 @@ interface KerneLocalization {
|
|
|
186
186
|
freePlan: string;
|
|
187
187
|
seePlans: string;
|
|
188
188
|
cancelNotice: string;
|
|
189
|
+
cancelSubscription: string;
|
|
190
|
+
canceling: string;
|
|
191
|
+
cancelConfirmTitle: string;
|
|
192
|
+
cancelConfirmBody: string;
|
|
193
|
+
cancelConfirmButton: string;
|
|
194
|
+
cancelConfirmDismiss: string;
|
|
189
195
|
changePlan: string;
|
|
190
196
|
current: string;
|
|
191
197
|
switchTo: string;
|
|
@@ -211,8 +217,30 @@ interface KerneLocalization {
|
|
|
211
217
|
subtitle: string;
|
|
212
218
|
used: string;
|
|
213
219
|
nothingMetered: string;
|
|
220
|
+
/** Overage ALLOW: past the included amount, tolerated and free. */
|
|
214
221
|
overage: string;
|
|
222
|
+
/** Overage BILL: past the included amount, charged on top of the plan. */
|
|
223
|
+
overageBilled: string;
|
|
224
|
+
/** Overage BLOCK only - ALLOW and BILL never "reach" a limit, they keep going. */
|
|
215
225
|
limitReached: string;
|
|
226
|
+
/** Overage BILL whose billing cap was hit: charging stopped, access didn't - the opposite of limitReached, not a variant of overageBilled. */
|
|
227
|
+
capReached: string;
|
|
228
|
+
/** Shown under a BILL entitlement once something has actually been billed this period. */
|
|
229
|
+
billedAmount: string;
|
|
230
|
+
loading: string;
|
|
231
|
+
loadFailed: string;
|
|
232
|
+
};
|
|
233
|
+
/** `<PricingTable>` - the marketing surface. Distinct from `billing.*`, the settings-page plan switcher. */
|
|
234
|
+
pricing: {
|
|
235
|
+
getStarted: string;
|
|
236
|
+
/** "{amount} / {interval}" - the caption under a price shown at a different cadence than it's billed. */
|
|
237
|
+
billedAt: string;
|
|
238
|
+
/** "Save {percent}%" - the label-switch hint. */
|
|
239
|
+
save: string;
|
|
240
|
+
/** Prefixes a QUOTA entitlement with no ceiling, e.g. "Unlimited projects". */
|
|
241
|
+
unlimited: string;
|
|
242
|
+
/** "+{count} more" - shown when `maxFeatures` truncates a plan's entitlement list. */
|
|
243
|
+
moreFeatures: string;
|
|
216
244
|
loading: string;
|
|
217
245
|
loadFailed: string;
|
|
218
246
|
};
|
|
@@ -186,6 +186,12 @@ interface KerneLocalization {
|
|
|
186
186
|
freePlan: string;
|
|
187
187
|
seePlans: string;
|
|
188
188
|
cancelNotice: string;
|
|
189
|
+
cancelSubscription: string;
|
|
190
|
+
canceling: string;
|
|
191
|
+
cancelConfirmTitle: string;
|
|
192
|
+
cancelConfirmBody: string;
|
|
193
|
+
cancelConfirmButton: string;
|
|
194
|
+
cancelConfirmDismiss: string;
|
|
189
195
|
changePlan: string;
|
|
190
196
|
current: string;
|
|
191
197
|
switchTo: string;
|
|
@@ -211,8 +217,30 @@ interface KerneLocalization {
|
|
|
211
217
|
subtitle: string;
|
|
212
218
|
used: string;
|
|
213
219
|
nothingMetered: string;
|
|
220
|
+
/** Overage ALLOW: past the included amount, tolerated and free. */
|
|
214
221
|
overage: string;
|
|
222
|
+
/** Overage BILL: past the included amount, charged on top of the plan. */
|
|
223
|
+
overageBilled: string;
|
|
224
|
+
/** Overage BLOCK only - ALLOW and BILL never "reach" a limit, they keep going. */
|
|
215
225
|
limitReached: string;
|
|
226
|
+
/** Overage BILL whose billing cap was hit: charging stopped, access didn't - the opposite of limitReached, not a variant of overageBilled. */
|
|
227
|
+
capReached: string;
|
|
228
|
+
/** Shown under a BILL entitlement once something has actually been billed this period. */
|
|
229
|
+
billedAmount: string;
|
|
230
|
+
loading: string;
|
|
231
|
+
loadFailed: string;
|
|
232
|
+
};
|
|
233
|
+
/** `<PricingTable>` - the marketing surface. Distinct from `billing.*`, the settings-page plan switcher. */
|
|
234
|
+
pricing: {
|
|
235
|
+
getStarted: string;
|
|
236
|
+
/** "{amount} / {interval}" - the caption under a price shown at a different cadence than it's billed. */
|
|
237
|
+
billedAt: string;
|
|
238
|
+
/** "Save {percent}%" - the label-switch hint. */
|
|
239
|
+
save: string;
|
|
240
|
+
/** Prefixes a QUOTA entitlement with no ceiling, e.g. "Unlimited projects". */
|
|
241
|
+
unlimited: string;
|
|
242
|
+
/** "+{count} more" - shown when `maxFeatures` truncates a plan's entitlement list. */
|
|
243
|
+
moreFeatures: string;
|
|
216
244
|
loading: string;
|
|
217
245
|
loadFailed: string;
|
|
218
246
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -17,25 +17,27 @@
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
var _chunkIMZFZ3P5cjs = require('./chunk-IMZFZ3P5.cjs');
|
|
21
23
|
|
|
22
24
|
// src/components.tsx
|
|
23
25
|
var _react = require('react'); var _react2 = _interopRequireDefault(_react);
|
|
24
26
|
var _jsxruntime = require('react/jsx-runtime');
|
|
25
27
|
function Authenticated({ children, fallback = null }) {
|
|
26
|
-
const { isAuthenticated } =
|
|
28
|
+
const { isAuthenticated } = _chunkIMZFZ3P5cjs.useAuth.call(void 0, );
|
|
27
29
|
return isAuthenticated ? children : fallback;
|
|
28
30
|
}
|
|
29
31
|
function Unauthenticated({ children, fallback = null }) {
|
|
30
|
-
const { isAuthenticated } =
|
|
32
|
+
const { isAuthenticated } = _chunkIMZFZ3P5cjs.useAuth.call(void 0, );
|
|
31
33
|
return !isAuthenticated ? children : fallback;
|
|
32
34
|
}
|
|
33
35
|
function AuthLoading({ children }) {
|
|
34
|
-
const client =
|
|
36
|
+
const client = _chunkIMZFZ3P5cjs.useClient.call(void 0, );
|
|
35
37
|
return client.isLoading ? children : null;
|
|
36
38
|
}
|
|
37
39
|
function HasSubscription({ children, fallback = null }) {
|
|
38
|
-
const client =
|
|
40
|
+
const client = _chunkIMZFZ3P5cjs.useClient.call(void 0, );
|
|
39
41
|
const [hasSubscription, setHasSubscription] = _react2.default.useState(null);
|
|
40
42
|
_react2.default.useEffect(() => {
|
|
41
43
|
client.getSubscription().then((sub) => {
|
|
@@ -47,22 +49,14 @@ function HasSubscription({ children, fallback = null }) {
|
|
|
47
49
|
if (hasSubscription === null) return null;
|
|
48
50
|
return hasSubscription ? children : fallback;
|
|
49
51
|
}
|
|
50
|
-
function
|
|
52
|
+
function Access({
|
|
51
53
|
children,
|
|
52
54
|
featureKey,
|
|
53
|
-
|
|
55
|
+
requested,
|
|
54
56
|
fallback = null
|
|
55
57
|
}) {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
_react2.default.useEffect(() => {
|
|
59
|
-
client.allows(featureKey, minimum).then((result) => {
|
|
60
|
-
setAllowed(result);
|
|
61
|
-
}).catch(() => {
|
|
62
|
-
setAllowed(false);
|
|
63
|
-
});
|
|
64
|
-
}, [client, featureKey, minimum]);
|
|
65
|
-
if (allowed === null) return null;
|
|
58
|
+
const { allowed, isLoading } = _chunkIMZFZ3P5cjs.useAccess.call(void 0, featureKey, requested);
|
|
59
|
+
if (isLoading) return null;
|
|
66
60
|
return allowed ? children : fallback;
|
|
67
61
|
}
|
|
68
62
|
function Protected({
|
|
@@ -72,12 +66,12 @@ function Protected({
|
|
|
72
66
|
authFallback = null,
|
|
73
67
|
billingFallback = null
|
|
74
68
|
}) {
|
|
75
|
-
const { isAuthenticated } =
|
|
69
|
+
const { isAuthenticated } = _chunkIMZFZ3P5cjs.useAuth.call(void 0, );
|
|
76
70
|
if (auth && !isAuthenticated) {
|
|
77
71
|
return authFallback;
|
|
78
72
|
}
|
|
79
73
|
if (featureKey) {
|
|
80
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
74
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Access, { featureKey, fallback: billingFallback, children });
|
|
81
75
|
}
|
|
82
76
|
return children;
|
|
83
77
|
}
|
|
@@ -183,4 +177,6 @@ function useKerneError() {
|
|
|
183
177
|
|
|
184
178
|
|
|
185
179
|
|
|
186
|
-
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
exports.Access = Access; exports.AuthLoading = AuthLoading; exports.Authenticated = Authenticated; exports.HasSubscription = HasSubscription; exports.KerneClient = _chunkIMZFZ3P5cjs.KerneClient; exports.KerneContext = _chunkIMZFZ3P5cjs.KerneContext; exports.KerneErrorBoundary = KerneErrorBoundary; exports.KerneProvider = _chunkIMZFZ3P5cjs.KerneProvider; exports.Protected = Protected; exports.Unauthenticated = Unauthenticated; exports.defaultLocalization = _chunkIMZFZ3P5cjs.defaultLocalization; exports.useAccess = _chunkIMZFZ3P5cjs.useAccess; exports.useAuth = _chunkIMZFZ3P5cjs.useAuth; exports.useAuthConfig = _chunkIMZFZ3P5cjs.useAuthConfig; exports.useCancelSubscription = _chunkIMZFZ3P5cjs.useCancelSubscription; exports.useChangePlan = _chunkIMZFZ3P5cjs.useChangePlan; exports.useCheckout = _chunkIMZFZ3P5cjs.useCheckout; exports.useClient = _chunkIMZFZ3P5cjs.useClient; exports.useEntitlements = _chunkIMZFZ3P5cjs.useEntitlements; exports.useInvitation = _chunkIMZFZ3P5cjs.useInvitation; exports.useKerneError = useKerneError; exports.usePlans = _chunkIMZFZ3P5cjs.usePlans; exports.usePortal = _chunkIMZFZ3P5cjs.usePortal; exports.useSubscription = _chunkIMZFZ3P5cjs.useSubscription; exports.useUsage = _chunkIMZFZ3P5cjs.useUsage; exports.useUser = _chunkIMZFZ3P5cjs.useUser; exports.useWaitlist = _chunkIMZFZ3P5cjs.useWaitlist;
|