@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 CHANGED
@@ -44,20 +44,32 @@ function LoginForm() {
44
44
 
45
45
  ## Gating a feature
46
46
 
47
- `Allows` (and the underlying `useAccess` hook) check the logged-in user automatically - no scope to pass, the SDK already knows who's authenticated.
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 { Allows } from '@kerne/react';
50
+ import { Access } from '@kerne/react';
51
51
 
52
52
  function ExportButton() {
53
53
  return (
54
- <Allows featureKey="export_pdf" fallback={<UpgradePrompt />}>
54
+ <Access featureKey="export_pdf" fallback={<UpgradePrompt />}>
55
55
  <button onClick={exportPdf}>Export as PDF</button>
56
- </Allows>
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 - billed as overage.",
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. `<Allows>`)
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
- scopeType: "USER"
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
- let mounted = true;
962
- client.getSubscription(productSlug).then((subscription) => {
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
- mounted = false;
1036
+ mountedRef.current = false;
973
1037
  };
974
- }, [client, productSlug]);
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
- 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.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;
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 - billed as overage.",
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. `<Allows>`)
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
- scopeType: "USER"
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
- let mounted = true;
962
- client.getSubscription(productSlug).then((subscription) => {
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
- mounted = false;
1036
+ mountedRef.current = false;
973
1037
  };
974
- }, [client, productSlug]);
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
- var _chunk7U3QBMA7cjs = require('./chunk-7U3QBMA7.cjs');
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 } = _chunk7U3QBMA7cjs.useAuth.call(void 0, );
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 } = _chunk7U3QBMA7cjs.useAuth.call(void 0, );
32
+ const { isAuthenticated } = _chunkIMZFZ3P5cjs.useAuth.call(void 0, );
31
33
  return !isAuthenticated ? children : fallback;
32
34
  }
33
35
  function AuthLoading({ children }) {
34
- const client = _chunk7U3QBMA7cjs.useClient.call(void 0, );
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 = _chunk7U3QBMA7cjs.useClient.call(void 0, );
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 Allows({
52
+ function Access({
51
53
  children,
52
54
  featureKey,
53
- minimum,
55
+ requested,
54
56
  fallback = null
55
57
  }) {
56
- const client = _chunk7U3QBMA7cjs.useClient.call(void 0, );
57
- const [allowed, setAllowed] = _react2.default.useState(null);
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 } = _chunk7U3QBMA7cjs.useAuth.call(void 0, );
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, Allows, { featureKey, fallback: billingFallback, children });
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
- exports.Allows = Allows; exports.AuthLoading = AuthLoading; exports.Authenticated = Authenticated; exports.HasSubscription = HasSubscription; exports.KerneClient = _chunk7U3QBMA7cjs.KerneClient; exports.KerneContext = _chunk7U3QBMA7cjs.KerneContext; exports.KerneErrorBoundary = KerneErrorBoundary; exports.KerneProvider = _chunk7U3QBMA7cjs.KerneProvider; exports.Protected = Protected; exports.Unauthenticated = Unauthenticated; exports.defaultLocalization = _chunk7U3QBMA7cjs.defaultLocalization; exports.useAccess = _chunk7U3QBMA7cjs.useAccess; exports.useAuth = _chunk7U3QBMA7cjs.useAuth; exports.useAuthConfig = _chunk7U3QBMA7cjs.useAuthConfig; exports.useCheckout = _chunk7U3QBMA7cjs.useCheckout; exports.useClient = _chunk7U3QBMA7cjs.useClient; exports.useEntitlements = _chunk7U3QBMA7cjs.useEntitlements; exports.useInvitation = _chunk7U3QBMA7cjs.useInvitation; exports.useKerneError = useKerneError; exports.usePlans = _chunk7U3QBMA7cjs.usePlans; exports.usePortal = _chunk7U3QBMA7cjs.usePortal; exports.useSubscription = _chunk7U3QBMA7cjs.useSubscription; exports.useUsage = _chunk7U3QBMA7cjs.useUsage; exports.useUser = _chunk7U3QBMA7cjs.useUser; exports.useWaitlist = _chunk7U3QBMA7cjs.useWaitlist;
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;