@solvapay/react 2.2.1 → 2.2.2-preview-09731417a0a7b4fd3afb4783fdf20b5ad293f63d

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @solvapay/react changelog
2
2
 
3
+ ## 2.2.2-preview-09731417a0a7b4fd3afb4783fdf20b5ad293f63d
4
+
5
+ ### Patch Changes
6
+
7
+ - 567db3e: The customer's active plan is no longer selectable in the plan picker. The active PAYG plan is no longer auto-selected — topping up happens from the account surface, not by re-activating the current plan from the list.
8
+ - Updated dependencies [c67e78e]
9
+ - Updated dependencies [dbd0108]
10
+ - Updated dependencies [c67e78e]
11
+ - Updated dependencies [c67e78e]
12
+ - Updated dependencies [c67e78e]
13
+ - @solvapay/mcp-core@0.4.2-preview-09731417a0a7b4fd3afb4783fdf20b5ad293f63d
14
+
3
15
  ## 2.2.1
4
16
 
5
17
  ### Patch Changes
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { _ as UsageSnapshot } from './useUsage-CfM9dQwB.js';
2
+ import { _ as UsageSnapshot } from './useUsage-DSPWQ37m.js';
3
3
 
4
4
  /**
5
5
  * `<UsageMeter>` compound primitive — renders the authenticated customer's
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { _ as UsageSnapshot } from './useUsage-x6DQG7xe.cjs';
2
+ import { _ as UsageSnapshot } from './useUsage-CRd_E6J3.cjs';
3
3
 
4
4
  /**
5
5
  * `<UsageMeter>` compound primitive — renders the authenticated customer's
@@ -8,7 +8,7 @@ import {
8
8
  useOpenExternal,
9
9
  useSolvaPay,
10
10
  useTransport
11
- } from "./chunk-LCBCOFXZ.js";
11
+ } from "./chunk-GPP4MY3I.js";
12
12
 
13
13
  // src/hooks/usePaymentMethod.ts
14
14
  import { useCallback, useEffect, useState } from "react";
@@ -1880,15 +1880,14 @@ function processPlans(raw, filter, sortBy) {
1880
1880
  if (filter) result = result.filter(filter);
1881
1881
  return result;
1882
1882
  }
1883
- function computeInitialIndex(plans, initialPlanRef, autoSelectFirstPaid) {
1883
+ function computeInitialIndex(plans, initialPlanRef, autoSelectFirstPaid, excludePlanRef) {
1884
1884
  if (plans.length === 0) return 0;
1885
1885
  if (initialPlanRef) {
1886
1886
  const idx = plans.findIndex((p) => p.reference === initialPlanRef);
1887
1887
  if (idx >= 0) return idx;
1888
1888
  }
1889
1889
  if (autoSelectFirstPaid) {
1890
- const idx = plans.findIndex((p) => p.requiresPayment !== false);
1891
- return idx >= 0 ? idx : 0;
1890
+ return plans.findIndex((p) => p.requiresPayment !== false && p.reference !== excludePlanRef);
1892
1891
  }
1893
1892
  return -1;
1894
1893
  }
@@ -1900,6 +1899,7 @@ function usePlans(options) {
1900
1899
  sortBy,
1901
1900
  autoSelectFirstPaid = false,
1902
1901
  initialPlanRef,
1902
+ excludePlanRef,
1903
1903
  selectionReady = true
1904
1904
  } = options;
1905
1905
  const solvaContext = useContext5(SolvaPayContext);
@@ -1913,6 +1913,7 @@ function usePlans(options) {
1913
1913
  const sortByRef = useRef3(sortBy);
1914
1914
  const autoSelectFirstPaidRef = useRef3(autoSelectFirstPaid);
1915
1915
  const initialPlanRefRef = useRef3(initialPlanRef);
1916
+ const excludePlanRefRef = useRef3(excludePlanRef);
1916
1917
  const selectionReadyRef = useRef3(selectionReady);
1917
1918
  const hasAppliedInitialRef = useRef3(false);
1918
1919
  const userHasSelectedRef = useRef3(false);
@@ -1924,7 +1925,7 @@ function usePlans(options) {
1924
1925
  }
1925
1926
  const processed = processPlans(cached.plans, filter, sortBy);
1926
1927
  if (processed.length === 0) return 0;
1927
- const idx = computeInitialIndex(processed, initialPlanRef, autoSelectFirstPaid);
1928
+ const idx = computeInitialIndex(processed, initialPlanRef, autoSelectFirstPaid, excludePlanRef);
1928
1929
  hasAppliedInitialRef.current = true;
1929
1930
  return idx;
1930
1931
  });
@@ -1953,6 +1954,9 @@ function usePlans(options) {
1953
1954
  useEffect2(() => {
1954
1955
  initialPlanRefRef.current = initialPlanRef;
1955
1956
  }, [initialPlanRef]);
1957
+ useEffect2(() => {
1958
+ excludePlanRefRef.current = excludePlanRef;
1959
+ }, [excludePlanRef]);
1956
1960
  useEffect2(() => {
1957
1961
  selectionReadyRef.current = selectionReady;
1958
1962
  }, [selectionReady]);
@@ -1967,7 +1971,8 @@ function usePlans(options) {
1967
1971
  const idx = computeInitialIndex(
1968
1972
  processedPlans,
1969
1973
  initialPlanRefRef.current,
1970
- autoSelectFirstPaidRef.current
1974
+ autoSelectFirstPaidRef.current,
1975
+ excludePlanRefRef.current
1971
1976
  );
1972
1977
  setSelectedPlanIndexState(idx);
1973
1978
  }, []);
@@ -1984,11 +1989,7 @@ function usePlans(options) {
1984
1989
  try {
1985
1990
  setLoading(true);
1986
1991
  const fetchedPlans = await cached.promise;
1987
- const processedPlans = processPlans(
1988
- fetchedPlans,
1989
- filterRef.current,
1990
- sortByRef.current
1991
- );
1992
+ const processedPlans = processPlans(fetchedPlans, filterRef.current, sortByRef.current);
1992
1993
  setPlans(processedPlans);
1993
1994
  setError(null);
1994
1995
  applyInitialSelection(processedPlans);
@@ -2000,11 +2001,7 @@ function usePlans(options) {
2000
2001
  return;
2001
2002
  }
2002
2003
  if (!force && cached && cached.plans.length > 0 && now - cached.timestamp < CACHE_DURATION3) {
2003
- const processedPlans = processPlans(
2004
- cached.plans,
2005
- filterRef.current,
2006
- sortByRef.current
2007
- );
2004
+ const processedPlans = processPlans(cached.plans, filterRef.current, sortByRef.current);
2008
2005
  setPlans(processedPlans);
2009
2006
  setLoading(false);
2010
2007
  setError(null);
@@ -2018,11 +2015,7 @@ function usePlans(options) {
2018
2015
  plansCache.set(productRef, { plans: [], timestamp: now, promise: fetchPromise });
2019
2016
  const fetchedPlans = await fetchPromise;
2020
2017
  plansCache.set(productRef, { plans: fetchedPlans, timestamp: now, promise: null });
2021
- const processedPlans = processPlans(
2022
- fetchedPlans,
2023
- filterRef.current,
2024
- sortByRef.current
2025
- );
2018
+ const processedPlans = processPlans(fetchedPlans, filterRef.current, sortByRef.current);
2026
2019
  setPlans(processedPlans);
2027
2020
  applyInitialSelection(processedPlans);
2028
2021
  } catch (err) {
@@ -5851,21 +5844,7 @@ var BalanceBadge = forwardRef8(function BalanceBadge2({ asChild, numberOnly, low
5851
5844
  });
5852
5845
 
5853
5846
  // src/primitives/PlanSelector.tsx
5854
- import {
5855
- createContext as createContext9,
5856
- forwardRef as forwardRef9,
5857
- useCallback as useCallback15,
5858
- useContext as useContext13,
5859
- useEffect as useEffect12,
5860
- useMemo as useMemo11,
5861
- useRef as useRef8,
5862
- useState as useState14
5863
- } from "react";
5864
-
5865
- // src/utils/isPayg.ts
5866
- function isPaygPlan(plan) {
5867
- return plan?.type === "usage-based" || plan?.type === "hybrid";
5868
- }
5847
+ import { createContext as createContext9, forwardRef as forwardRef9, useCallback as useCallback15, useContext as useContext13, useMemo as useMemo11, useState as useState14 } from "react";
5869
5848
 
5870
5849
  // src/utils/planPricing.ts
5871
5850
  import { headlineCharges } from "@solvapay/core";
@@ -5940,19 +5919,20 @@ var Root5 = forwardRef9(function PlanSelectorRoot(props, forwardedRef) {
5940
5919
  () => fetcher ?? ((ref) => defaultListPlans(ref, _config)),
5941
5920
  [fetcher, _config]
5942
5921
  );
5922
+ const autoCurrentPlanRef = useMemo11(() => {
5923
+ const active = purchases.filter((p) => p.status === "active").sort((a, b) => new Date(b.startDate).getTime() - new Date(a.startDate).getTime())[0];
5924
+ return active?.planSnapshot?.reference ?? null;
5925
+ }, [purchases]);
5926
+ const resolvedCurrentPlanRef = currentPlanRef === null ? null : currentPlanRef ?? autoCurrentPlanRef;
5943
5927
  const { plans, selectedPlan, selectPlan, setSelectedPlanIndex, loading, error } = usePlans({
5944
5928
  productRef,
5945
5929
  fetcher: effectiveFetcher,
5946
5930
  filter,
5947
5931
  sortBy,
5948
5932
  autoSelectFirstPaid,
5949
- initialPlanRef
5933
+ initialPlanRef,
5934
+ excludePlanRef: resolvedCurrentPlanRef
5950
5935
  });
5951
- const autoCurrentPlanRef = useMemo11(() => {
5952
- const active = purchases.filter((p) => p.status === "active").sort((a, b) => new Date(b.startDate).getTime() - new Date(a.startDate).getTime())[0];
5953
- return active?.planSnapshot?.reference ?? null;
5954
- }, [purchases]);
5955
- const resolvedCurrentPlanRef = currentPlanRef === null ? null : currentPlanRef ?? autoCurrentPlanRef;
5956
5936
  const isCurrent = useCallback15(
5957
5937
  (ref) => resolvedCurrentPlanRef === ref,
5958
5938
  [resolvedCurrentPlanRef]
@@ -5961,19 +5941,17 @@ var Root5 = forwardRef9(function PlanSelectorRoot(props, forwardedRef) {
5961
5941
  (ref) => plans.find((p) => p.reference === ref)?.requiresPayment === false,
5962
5942
  [plans]
5963
5943
  );
5964
- const isPopular = useCallback15(
5965
- (ref) => popularPlanRef === ref,
5966
- [popularPlanRef]
5967
- );
5944
+ const isPopular = useCallback15((ref) => popularPlanRef === ref, [popularPlanRef]);
5968
5945
  const select = useCallback15(
5969
5946
  (ref) => {
5970
5947
  const plan = plans.find((p) => p.reference === ref);
5971
5948
  if (!plan) return;
5972
5949
  if (plan.requiresPayment === false) return;
5950
+ if (isCurrent(ref)) return;
5973
5951
  selectPlan(ref);
5974
5952
  onSelect?.(ref, plan);
5975
5953
  },
5976
- [plans, selectPlan, onSelect]
5954
+ [plans, selectPlan, onSelect, isCurrent]
5977
5955
  );
5978
5956
  const clearSelection = useCallback15(() => {
5979
5957
  setSelectedPlanIndex(-1);
@@ -5996,22 +5974,6 @@ var Root5 = forwardRef9(function PlanSelectorRoot(props, forwardedRef) {
5996
5974
  setSelectedCurrencies((current) => ({ ...current, [planRef]: currency }));
5997
5975
  }, []);
5998
5976
  const selectedCurrency = selectedPlan ? getSelectedOption(selectedPlan).currency : null;
5999
- const autoCurrentAppliedKeyRef = useRef8(null);
6000
- useEffect12(() => {
6001
- if (autoCurrentAppliedKeyRef.current === productRef) return;
6002
- if (selectedPlanRef) {
6003
- autoCurrentAppliedKeyRef.current = productRef;
6004
- return;
6005
- }
6006
- if (!resolvedCurrentPlanRef || plans.length === 0) return;
6007
- const currentPlan = plans.find((p) => p.reference === resolvedCurrentPlanRef);
6008
- if (!currentPlan || !isPaygPlan(currentPlan)) {
6009
- autoCurrentAppliedKeyRef.current = productRef;
6010
- return;
6011
- }
6012
- autoCurrentAppliedKeyRef.current = productRef;
6013
- select(resolvedCurrentPlanRef);
6014
- }, [productRef, plans, resolvedCurrentPlanRef, selectedPlanRef, select]);
6015
5977
  const ctx = useMemo11(
6016
5978
  () => ({
6017
5979
  plans,
@@ -6088,9 +6050,8 @@ var Grid = forwardRef9(function PlanSelectorGrid({ children, ...rest }, forwarde
6088
6050
  const isFree = ctx.isFree(plan.reference);
6089
6051
  const isPopular = ctx.isPopular(plan.reference);
6090
6052
  const selected = ctx.selectedPlanRef === plan.reference;
6091
- const isPaygCurrent = isCurrent && isPaygPlan(plan);
6092
- const disabled = isFree || isCurrent && !isPaygCurrent;
6093
- const state = isCurrent && !isPaygCurrent ? "current" : selected ? "selected" : isCurrent ? "current" : isFree ? "disabled" : "idle";
6053
+ const disabled = isFree || isCurrent;
6054
+ const state = isCurrent ? "current" : selected ? "selected" : isFree ? "disabled" : "idle";
6094
6055
  const pricingOptions = getPlanPricingOptions(plan);
6095
6056
  const selectedOption = ctx.getSelectedOption(plan);
6096
6057
  const cardCtx = {
@@ -6588,7 +6549,7 @@ function useTransport() {
6588
6549
  }
6589
6550
 
6590
6551
  // src/hooks/useLimits.ts
6591
- import { useCallback as useCallback19, useEffect as useEffect13, useRef as useRef9, useState as useState16 } from "react";
6552
+ import { useCallback as useCallback19, useEffect as useEffect12, useRef as useRef8, useState as useState16 } from "react";
6592
6553
  var CACHE_TTL_MS = 1e4;
6593
6554
  var OPTIMISTIC_GRACE_MS = 8e3;
6594
6555
  var limitsCache = /* @__PURE__ */ new Map();
@@ -6626,12 +6587,12 @@ function useLimits(options) {
6626
6587
  setData(null);
6627
6588
  }
6628
6589
  const unlimited = data === null ? null : isUnlimited(data.remaining);
6629
- const optimisticTimerRef = useRef9(null);
6630
- const unlimitedRef = useRef9(false);
6631
- useEffect13(() => {
6590
+ const optimisticTimerRef = useRef8(null);
6591
+ const unlimitedRef = useRef8(false);
6592
+ useEffect12(() => {
6632
6593
  unlimitedRef.current = unlimited === true;
6633
6594
  }, [unlimited]);
6634
- useEffect13(() => {
6595
+ useEffect12(() => {
6635
6596
  return () => {
6636
6597
  if (optimisticTimerRef.current) clearTimeout(optimisticTimerRef.current);
6637
6598
  };
@@ -6694,11 +6655,11 @@ function useLimits(options) {
6694
6655
  },
6695
6656
  [transport, customerRef, productRef, meterName2, enabled, attachToFetch]
6696
6657
  );
6697
- useEffect13(() => {
6658
+ useEffect12(() => {
6698
6659
  fetchLimits(false);
6699
6660
  }, [fetchLimits]);
6700
- const prevPurchasesRef = useRef9(null);
6701
- useEffect13(() => {
6661
+ const prevPurchasesRef = useRef8(null);
6662
+ useEffect12(() => {
6702
6663
  if (prevPurchasesRef.current !== null && prevPurchasesRef.current !== purchase.purchases) {
6703
6664
  fetchLimits(true).catch(() => {
6704
6665
  });
@@ -6764,7 +6725,7 @@ function useLimits(options) {
6764
6725
 
6765
6726
  // src/hooks/useUsage.ts
6766
6727
  import { countsUsage } from "@solvapay/core";
6767
- import { useCallback as useCallback20, useEffect as useEffect14, useMemo as useMemo15, useState as useState17 } from "react";
6728
+ import { useCallback as useCallback20, useEffect as useEffect13, useMemo as useMemo15, useState as useState17 } from "react";
6768
6729
  var seededUsage = null;
6769
6730
  var usageSeedGeneration = 0;
6770
6731
  function seedUsageSnapshot(usage) {
@@ -6826,7 +6787,7 @@ function useUsage() {
6826
6787
  [activePurchase, limitRemaining, unlimited, meterName2, limitUsed, limit]
6827
6788
  );
6828
6789
  const activePurchaseRef = activePurchase?.reference ?? null;
6829
- useEffect14(() => {
6790
+ useEffect13(() => {
6830
6791
  setOverride(seededUsage);
6831
6792
  }, [activePurchaseRef]);
6832
6793
  const usage = override ?? derived;
@@ -7077,7 +7038,7 @@ function useUsageMeter() {
7077
7038
  }
7078
7039
 
7079
7040
  // src/hooks/useAutoRecharge.ts
7080
- import { useCallback as useCallback21, useEffect as useEffect15, useRef as useRef10, useState as useState18 } from "react";
7041
+ import { useCallback as useCallback21, useEffect as useEffect14, useRef as useRef9, useState as useState18 } from "react";
7081
7042
  function mergeAutoRechargeConfig(config, display) {
7082
7043
  return display ? { ...config, display } : config;
7083
7044
  }
@@ -7101,7 +7062,7 @@ function useAutoRecharge() {
7101
7062
  const [saving, setSaving] = useState18(false);
7102
7063
  const [disabling, setDisabling] = useState18(false);
7103
7064
  const [error, setError] = useState18(null);
7104
- const requestSeq = useRef10(0);
7065
+ const requestSeq = useRef9(0);
7105
7066
  const load = useCallback21(
7106
7067
  async (force = false) => {
7107
7068
  const seq = requestSeq.current;
@@ -7161,10 +7122,10 @@ function useAutoRecharge() {
7161
7122
  },
7162
7123
  [_config, key]
7163
7124
  );
7164
- useEffect15(() => {
7125
+ useEffect14(() => {
7165
7126
  void load();
7166
7127
  }, [load]);
7167
- useEffect15(() => {
7128
+ useEffect14(() => {
7168
7129
  return subscribeAutoRecharge(key, () => {
7169
7130
  const cached = autoRechargeCache.get(key);
7170
7131
  if (cached) {
@@ -7557,7 +7518,7 @@ function flipUnitValue(anchor, targetUnit, currency, creditsPerMinorUnit, displa
7557
7518
  }
7558
7519
 
7559
7520
  // src/hooks/useCheckoutFlow.ts
7560
- import { useCallback as useCallback22, useMemo as useMemo17, useRef as useRef11, useState as useState19 } from "react";
7521
+ import { useCallback as useCallback22, useMemo as useMemo17, useRef as useRef10, useState as useState19 } from "react";
7561
7522
 
7562
7523
  // src/primitives/checkout/shared.ts
7563
7524
  import {
@@ -7568,6 +7529,13 @@ import {
7568
7529
  planPricingShape,
7569
7530
  usageRate
7570
7531
  } from "@solvapay/core";
7532
+
7533
+ // src/utils/isPayg.ts
7534
+ function isPaygPlan(plan) {
7535
+ return plan?.type === "usage-based" || plan?.type === "hybrid";
7536
+ }
7537
+
7538
+ // src/primitives/checkout/shared.ts
7571
7539
  function isPayg(plan) {
7572
7540
  return isPaygPlan(plan ?? null);
7573
7541
  }
@@ -7676,10 +7644,10 @@ function resolveInitialCheckoutStep(initialStep) {
7676
7644
  }
7677
7645
  function useCheckoutFlow(opts) {
7678
7646
  const { productRef, initialStep = "plan", initialAmountMinor = null } = opts;
7679
- const onPlanSelectRef = useRef11(opts.onPlanSelect);
7680
- const onAmountSelectRef = useRef11(opts.onAmountSelect);
7681
- const onPurchaseSuccessRef = useRef11(opts.onPurchaseSuccess);
7682
- const onErrorRef = useRef11(opts.onError);
7647
+ const onPlanSelectRef = useRef10(opts.onPlanSelect);
7648
+ const onAmountSelectRef = useRef10(opts.onAmountSelect);
7649
+ const onPurchaseSuccessRef = useRef10(opts.onPurchaseSuccess);
7650
+ const onErrorRef = useRef10(opts.onError);
7683
7651
  onPlanSelectRef.current = opts.onPlanSelect;
7684
7652
  onAmountSelectRef.current = opts.onAmountSelect;
7685
7653
  onPurchaseSuccessRef.current = opts.onPurchaseSuccess;
@@ -7712,7 +7680,7 @@ function useCheckoutFlow(opts) {
7712
7680
  const [selectedAmountMinor, setSelectedAmountMinor] = useState19(initialAmountMinor);
7713
7681
  const [successMeta, setSuccessMeta] = useState19(null);
7714
7682
  const [error, setError] = useState19(null);
7715
- const selectedAmountMinorRef = useRef11(initialAmountMinor);
7683
+ const selectedAmountMinorRef = useRef10(initialAmountMinor);
7716
7684
  const selectedPlan = planCtx.selectedPlan;
7717
7685
  const selectedPlanRef = planCtx.selectedPlanRef;
7718
7686
  const selectedPlanShape = toBootstrapPlanLike(selectedPlan);
@@ -8090,7 +8058,6 @@ export {
8090
8058
  TopupForm,
8091
8059
  useTopupForm,
8092
8060
  BalanceBadge,
8093
- isPaygPlan,
8094
8061
  resolvePlanPricingOption,
8095
8062
  PlanSelectorRoot2 as PlanSelectorRoot,
8096
8063
  PlanSelectorHeading2 as PlanSelectorHeading,
@@ -8133,6 +8100,7 @@ export {
8133
8100
  Empty,
8134
8101
  UsageMeter,
8135
8102
  useUsageMeter,
8103
+ isPaygPlan,
8136
8104
  isPayg,
8137
8105
  planSortByPaygFirstThenAsc,
8138
8106
  buildDefaultCheckoutPlanFilter,
@@ -46,7 +46,7 @@ import {
46
46
  useTopupAmountSelector,
47
47
  validateAutoRechargeForm,
48
48
  withPaymentElementDefaults
49
- } from "./chunk-LCBCOFXZ.js";
49
+ } from "./chunk-GPP4MY3I.js";
50
50
 
51
51
  // src/TopupForm.tsx
52
52
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,4 +1,4 @@
1
- import { a4 as components, b as Plan, P as PaymentFormProps, a as PrefillCustomer, A as ActivationResult, s as UseTopupAmountSelectorReturn, a5 as AutoRechargeInput, u as AutoRechargeConfig, a6 as AutoRechargeDisplayBlock, E as CheckoutStep, O as SuccessMeta } from './useUsage-x6DQG7xe.cjs';
1
+ import { a4 as components, b as Plan, P as PaymentFormProps, a as PrefillCustomer, A as ActivationResult, s as UseTopupAmountSelectorReturn, a5 as AutoRechargeInput, u as AutoRechargeConfig, a6 as AutoRechargeDisplayBlock, E as CheckoutStep, O as SuccessMeta } from './useUsage-CRd_E6J3.cjs';
2
2
  import React from 'react';
3
3
  import { PaymentElement, CardElement } from '@stripe/react-stripe-js';
4
4
  import { TaxBreakdown } from '@solvapay/core';
@@ -76,6 +76,10 @@ type PaywallGateRecoveryFields = {
76
76
  shortfallCredits?: number;
77
77
  /** How many calls the current allowance or wallet still covers. */
78
78
  remainingCalls?: number;
79
+ /** Credits per minor currency unit, from the limits balance peg. */
80
+ creditsPerMinorUnit?: number;
81
+ /** USD → display-currency rate used with `creditsPerMinorUnit`. */
82
+ displayExchangeRate?: number;
79
83
  /** Active purchase reference when the customer already holds a purchase. */
80
84
  purchaseRef?: string;
81
85
  /** Purchase/plan status when the backend sent one. */
@@ -1,4 +1,4 @@
1
- import { a4 as components, b as Plan, P as PaymentFormProps, a as PrefillCustomer, A as ActivationResult, s as UseTopupAmountSelectorReturn, a5 as AutoRechargeInput, u as AutoRechargeConfig, a6 as AutoRechargeDisplayBlock, E as CheckoutStep, O as SuccessMeta } from './useUsage-CfM9dQwB.js';
1
+ import { a4 as components, b as Plan, P as PaymentFormProps, a as PrefillCustomer, A as ActivationResult, s as UseTopupAmountSelectorReturn, a5 as AutoRechargeInput, u as AutoRechargeConfig, a6 as AutoRechargeDisplayBlock, E as CheckoutStep, O as SuccessMeta } from './useUsage-DSPWQ37m.js';
2
2
  import React from 'react';
3
3
  import { PaymentElement, CardElement } from '@stripe/react-stripe-js';
4
4
  import { TaxBreakdown } from '@solvapay/core';
@@ -76,6 +76,10 @@ type PaywallGateRecoveryFields = {
76
76
  shortfallCredits?: number;
77
77
  /** How many calls the current allowance or wallet still covers. */
78
78
  remainingCalls?: number;
79
+ /** Credits per minor currency unit, from the limits balance peg. */
80
+ creditsPerMinorUnit?: number;
81
+ /** USD → display-currency rate used with `creditsPerMinorUnit`. */
82
+ displayExchangeRate?: number;
79
83
  /** Active purchase reference when the customer already holds a purchase. */
80
84
  purchaseRef?: string;
81
85
  /** Purchase/plan status when the backend sent one. */
package/dist/index.cjs CHANGED
@@ -2330,15 +2330,14 @@ function processPlans(raw, filter, sortBy) {
2330
2330
  if (filter) result = result.filter(filter);
2331
2331
  return result;
2332
2332
  }
2333
- function computeInitialIndex(plans, initialPlanRef, autoSelectFirstPaid) {
2333
+ function computeInitialIndex(plans, initialPlanRef, autoSelectFirstPaid, excludePlanRef) {
2334
2334
  if (plans.length === 0) return 0;
2335
2335
  if (initialPlanRef) {
2336
2336
  const idx = plans.findIndex((p) => p.reference === initialPlanRef);
2337
2337
  if (idx >= 0) return idx;
2338
2338
  }
2339
2339
  if (autoSelectFirstPaid) {
2340
- const idx = plans.findIndex((p) => p.requiresPayment !== false);
2341
- return idx >= 0 ? idx : 0;
2340
+ return plans.findIndex((p) => p.requiresPayment !== false && p.reference !== excludePlanRef);
2342
2341
  }
2343
2342
  return -1;
2344
2343
  }
@@ -2350,6 +2349,7 @@ function usePlans(options) {
2350
2349
  sortBy,
2351
2350
  autoSelectFirstPaid = false,
2352
2351
  initialPlanRef,
2352
+ excludePlanRef,
2353
2353
  selectionReady = true
2354
2354
  } = options;
2355
2355
  const solvaContext = (0, import_react10.useContext)(SolvaPayContext);
@@ -2363,6 +2363,7 @@ function usePlans(options) {
2363
2363
  const sortByRef = (0, import_react10.useRef)(sortBy);
2364
2364
  const autoSelectFirstPaidRef = (0, import_react10.useRef)(autoSelectFirstPaid);
2365
2365
  const initialPlanRefRef = (0, import_react10.useRef)(initialPlanRef);
2366
+ const excludePlanRefRef = (0, import_react10.useRef)(excludePlanRef);
2366
2367
  const selectionReadyRef = (0, import_react10.useRef)(selectionReady);
2367
2368
  const hasAppliedInitialRef = (0, import_react10.useRef)(false);
2368
2369
  const userHasSelectedRef = (0, import_react10.useRef)(false);
@@ -2374,7 +2375,7 @@ function usePlans(options) {
2374
2375
  }
2375
2376
  const processed = processPlans(cached.plans, filter, sortBy);
2376
2377
  if (processed.length === 0) return 0;
2377
- const idx = computeInitialIndex(processed, initialPlanRef, autoSelectFirstPaid);
2378
+ const idx = computeInitialIndex(processed, initialPlanRef, autoSelectFirstPaid, excludePlanRef);
2378
2379
  hasAppliedInitialRef.current = true;
2379
2380
  return idx;
2380
2381
  });
@@ -2403,6 +2404,9 @@ function usePlans(options) {
2403
2404
  (0, import_react10.useEffect)(() => {
2404
2405
  initialPlanRefRef.current = initialPlanRef;
2405
2406
  }, [initialPlanRef]);
2407
+ (0, import_react10.useEffect)(() => {
2408
+ excludePlanRefRef.current = excludePlanRef;
2409
+ }, [excludePlanRef]);
2406
2410
  (0, import_react10.useEffect)(() => {
2407
2411
  selectionReadyRef.current = selectionReady;
2408
2412
  }, [selectionReady]);
@@ -2417,7 +2421,8 @@ function usePlans(options) {
2417
2421
  const idx = computeInitialIndex(
2418
2422
  processedPlans,
2419
2423
  initialPlanRefRef.current,
2420
- autoSelectFirstPaidRef.current
2424
+ autoSelectFirstPaidRef.current,
2425
+ excludePlanRefRef.current
2421
2426
  );
2422
2427
  setSelectedPlanIndexState(idx);
2423
2428
  }, []);
@@ -2434,11 +2439,7 @@ function usePlans(options) {
2434
2439
  try {
2435
2440
  setLoading(true);
2436
2441
  const fetchedPlans = await cached.promise;
2437
- const processedPlans = processPlans(
2438
- fetchedPlans,
2439
- filterRef.current,
2440
- sortByRef.current
2441
- );
2442
+ const processedPlans = processPlans(fetchedPlans, filterRef.current, sortByRef.current);
2442
2443
  setPlans(processedPlans);
2443
2444
  setError(null);
2444
2445
  applyInitialSelection(processedPlans);
@@ -2450,11 +2451,7 @@ function usePlans(options) {
2450
2451
  return;
2451
2452
  }
2452
2453
  if (!force && cached && cached.plans.length > 0 && now - cached.timestamp < CACHE_DURATION3) {
2453
- const processedPlans = processPlans(
2454
- cached.plans,
2455
- filterRef.current,
2456
- sortByRef.current
2457
- );
2454
+ const processedPlans = processPlans(cached.plans, filterRef.current, sortByRef.current);
2458
2455
  setPlans(processedPlans);
2459
2456
  setLoading(false);
2460
2457
  setError(null);
@@ -2468,11 +2465,7 @@ function usePlans(options) {
2468
2465
  plansCache.set(productRef, { plans: [], timestamp: now, promise: fetchPromise });
2469
2466
  const fetchedPlans = await fetchPromise;
2470
2467
  plansCache.set(productRef, { plans: fetchedPlans, timestamp: now, promise: null });
2471
- const processedPlans = processPlans(
2472
- fetchedPlans,
2473
- filterRef.current,
2474
- sortByRef.current
2475
- );
2468
+ const processedPlans = processPlans(fetchedPlans, filterRef.current, sortByRef.current);
2476
2469
  setPlans(processedPlans);
2477
2470
  applyInitialSelection(processedPlans);
2478
2471
  } catch (err) {
@@ -6271,11 +6264,6 @@ var import_react32 = require("react");
6271
6264
  // src/primitives/PlanSelector.tsx
6272
6265
  var import_react30 = require("react");
6273
6266
 
6274
- // src/utils/isPayg.ts
6275
- function isPaygPlan(plan) {
6276
- return plan?.type === "usage-based" || plan?.type === "hybrid";
6277
- }
6278
-
6279
6267
  // src/utils/planPricing.ts
6280
6268
  var import_core7 = require("@solvapay/core");
6281
6269
  function getPlanPricingOptions(plan) {
@@ -6349,19 +6337,20 @@ var Root6 = (0, import_react30.forwardRef)(function PlanSelectorRoot(props, forw
6349
6337
  () => fetcher ?? ((ref) => defaultListPlans(ref, _config)),
6350
6338
  [fetcher, _config]
6351
6339
  );
6340
+ const autoCurrentPlanRef = (0, import_react30.useMemo)(() => {
6341
+ const active = purchases.filter((p) => p.status === "active").sort((a, b) => new Date(b.startDate).getTime() - new Date(a.startDate).getTime())[0];
6342
+ return active?.planSnapshot?.reference ?? null;
6343
+ }, [purchases]);
6344
+ const resolvedCurrentPlanRef = currentPlanRef === null ? null : currentPlanRef ?? autoCurrentPlanRef;
6352
6345
  const { plans, selectedPlan, selectPlan, setSelectedPlanIndex, loading, error } = usePlans({
6353
6346
  productRef,
6354
6347
  fetcher: effectiveFetcher,
6355
6348
  filter,
6356
6349
  sortBy,
6357
6350
  autoSelectFirstPaid,
6358
- initialPlanRef
6351
+ initialPlanRef,
6352
+ excludePlanRef: resolvedCurrentPlanRef
6359
6353
  });
6360
- const autoCurrentPlanRef = (0, import_react30.useMemo)(() => {
6361
- const active = purchases.filter((p) => p.status === "active").sort((a, b) => new Date(b.startDate).getTime() - new Date(a.startDate).getTime())[0];
6362
- return active?.planSnapshot?.reference ?? null;
6363
- }, [purchases]);
6364
- const resolvedCurrentPlanRef = currentPlanRef === null ? null : currentPlanRef ?? autoCurrentPlanRef;
6365
6354
  const isCurrent = (0, import_react30.useCallback)(
6366
6355
  (ref) => resolvedCurrentPlanRef === ref,
6367
6356
  [resolvedCurrentPlanRef]
@@ -6370,19 +6359,17 @@ var Root6 = (0, import_react30.forwardRef)(function PlanSelectorRoot(props, forw
6370
6359
  (ref) => plans.find((p) => p.reference === ref)?.requiresPayment === false,
6371
6360
  [plans]
6372
6361
  );
6373
- const isPopular = (0, import_react30.useCallback)(
6374
- (ref) => popularPlanRef === ref,
6375
- [popularPlanRef]
6376
- );
6362
+ const isPopular = (0, import_react30.useCallback)((ref) => popularPlanRef === ref, [popularPlanRef]);
6377
6363
  const select = (0, import_react30.useCallback)(
6378
6364
  (ref) => {
6379
6365
  const plan = plans.find((p) => p.reference === ref);
6380
6366
  if (!plan) return;
6381
6367
  if (plan.requiresPayment === false) return;
6368
+ if (isCurrent(ref)) return;
6382
6369
  selectPlan(ref);
6383
6370
  onSelect?.(ref, plan);
6384
6371
  },
6385
- [plans, selectPlan, onSelect]
6372
+ [plans, selectPlan, onSelect, isCurrent]
6386
6373
  );
6387
6374
  const clearSelection = (0, import_react30.useCallback)(() => {
6388
6375
  setSelectedPlanIndex(-1);
@@ -6405,22 +6392,6 @@ var Root6 = (0, import_react30.forwardRef)(function PlanSelectorRoot(props, forw
6405
6392
  setSelectedCurrencies((current) => ({ ...current, [planRef]: currency }));
6406
6393
  }, []);
6407
6394
  const selectedCurrency = selectedPlan ? getSelectedOption(selectedPlan).currency : null;
6408
- const autoCurrentAppliedKeyRef = (0, import_react30.useRef)(null);
6409
- (0, import_react30.useEffect)(() => {
6410
- if (autoCurrentAppliedKeyRef.current === productRef) return;
6411
- if (selectedPlanRef) {
6412
- autoCurrentAppliedKeyRef.current = productRef;
6413
- return;
6414
- }
6415
- if (!resolvedCurrentPlanRef || plans.length === 0) return;
6416
- const currentPlan = plans.find((p) => p.reference === resolvedCurrentPlanRef);
6417
- if (!currentPlan || !isPaygPlan(currentPlan)) {
6418
- autoCurrentAppliedKeyRef.current = productRef;
6419
- return;
6420
- }
6421
- autoCurrentAppliedKeyRef.current = productRef;
6422
- select(resolvedCurrentPlanRef);
6423
- }, [productRef, plans, resolvedCurrentPlanRef, selectedPlanRef, select]);
6424
6395
  const ctx = (0, import_react30.useMemo)(
6425
6396
  () => ({
6426
6397
  plans,
@@ -6497,9 +6468,8 @@ var Grid = (0, import_react30.forwardRef)(function PlanSelectorGrid({ children,
6497
6468
  const isFree = ctx.isFree(plan.reference);
6498
6469
  const isPopular = ctx.isPopular(plan.reference);
6499
6470
  const selected = ctx.selectedPlanRef === plan.reference;
6500
- const isPaygCurrent = isCurrent && isPaygPlan(plan);
6501
- const disabled = isFree || isCurrent && !isPaygCurrent;
6502
- const state = isCurrent && !isPaygCurrent ? "current" : selected ? "selected" : isCurrent ? "current" : isFree ? "disabled" : "idle";
6471
+ const disabled = isFree || isCurrent;
6472
+ const state = isCurrent ? "current" : selected ? "selected" : isFree ? "disabled" : "idle";
6503
6473
  const pricingOptions = getPlanPricingOptions(plan);
6504
6474
  const selectedOption = ctx.getSelectedOption(plan);
6505
6475
  const cardCtx = {
@@ -8703,6 +8673,13 @@ var UsageMeter = Object.assign(Root10, {
8703
8673
 
8704
8674
  // src/primitives/checkout/shared.ts
8705
8675
  var import_core10 = require("@solvapay/core");
8676
+
8677
+ // src/utils/isPayg.ts
8678
+ function isPaygPlan(plan) {
8679
+ return plan?.type === "usage-based" || plan?.type === "hybrid";
8680
+ }
8681
+
8682
+ // src/primitives/checkout/shared.ts
8706
8683
  function isPayg(plan) {
8707
8684
  return isPaygPlan(plan ?? null);
8708
8685
  }