@stigg/react-sdk 4.13.2 → 4.15.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/components/common/TiersSelectContainer.d.ts +8 -3
- package/dist/components/common/VolumeBulkSelect.d.ts +5 -0
- package/dist/components/common/VolumePerUnitInput.d.ts +5 -0
- package/dist/components/customerPortal/CustomerPortal.d.ts +2 -2
- package/dist/components/customerPortal/CustomerPortalContainer.d.ts +4 -0
- package/dist/components/customerPortal/index.d.ts +3 -0
- package/dist/components/customerPortal/subscriptionOverview/SubscriptionsOverview.d.ts +2 -1
- package/dist/components/customerPortal/subscriptionOverview/SubscriptionsOverviewHeader.d.ts +2 -1
- package/dist/components/customerPortal/subscriptionOverview/charges/ChargeItem.d.ts +2 -1
- package/dist/components/customerPortal/subscriptionOverview/charges/ChargeList.d.ts +2 -1
- package/dist/components/customerPortal/subscriptionOverview/subscriptionView/SubscriptionView.d.ts +2 -1
- package/dist/components/customerPortal/subscriptionOverview/subscriptionView/TrialPanel.d.ts +2 -1
- package/dist/components/customerPortal/types.d.ts +10 -1
- package/dist/components/customerPortal/usage/CustomerUsageData.d.ts +2 -1
- package/dist/components/customerPortal/usage/featureUsage/EntitlementCTAButton.d.ts +2 -1
- package/dist/components/customerPortal/usage/featureUsage/FeatureUsage.d.ts +2 -1
- package/dist/components/paywall/PlanOfferingButton.d.ts +2 -1
- package/dist/components/paywall/PlanPrice.d.ts +3 -1
- package/dist/components/paywall/index.d.ts +1 -1
- package/dist/components/paywall/paywallTextOverrides.d.ts +1 -1
- package/dist/components/utils/getPaidPriceText.d.ts +2 -1
- package/dist/components/utils/getPlanPrice.d.ts +1 -1
- package/dist/components/utils/priceTierUtils.d.ts +3 -2
- package/dist/index.d.ts +3 -3
- package/dist/react-sdk.cjs.development.js +555 -361
- package/dist/react-sdk.cjs.development.js.map +1 -1
- package/dist/react-sdk.cjs.production.min.js +1 -1
- package/dist/react-sdk.cjs.production.min.js.map +1 -1
- package/dist/react-sdk.esm.js +589 -388
- package/dist/react-sdk.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/components/checkout/hooks/usePlanStepModel.ts +3 -3
- package/src/components/checkout/steps/plan/CheckoutChargeList.tsx +10 -2
- package/src/components/common/TiersSelectContainer.tsx +33 -62
- package/src/components/common/VolumeBulkSelect.tsx +68 -0
- package/src/components/common/VolumePerUnitInput.tsx +40 -0
- package/src/components/customerPortal/CustomerPortal.tsx +2 -2
- package/src/components/customerPortal/CustomerPortalContainer.tsx +8 -3
- package/src/components/customerPortal/index.ts +3 -0
- package/src/components/customerPortal/subscriptionOverview/SubscriptionsOverview.tsx +2 -1
- package/src/components/customerPortal/subscriptionOverview/SubscriptionsOverviewHeader.tsx +7 -2
- package/src/components/customerPortal/subscriptionOverview/charges/ChargeItem.tsx +2 -1
- package/src/components/customerPortal/subscriptionOverview/charges/ChargeList.tsx +2 -1
- package/src/components/customerPortal/subscriptionOverview/subscriptionView/SubscriptionView.tsx +2 -1
- package/src/components/customerPortal/subscriptionOverview/subscriptionView/TrialPanel.tsx +6 -2
- package/src/components/customerPortal/types.ts +15 -1
- package/src/components/customerPortal/usage/CustomerUsageData.tsx +2 -1
- package/src/components/customerPortal/usage/featureUsage/EntitlementCTAButton.tsx +6 -3
- package/src/components/customerPortal/usage/featureUsage/FeatureUsage.tsx +2 -1
- package/src/components/paywall/PlanOffering.tsx +15 -6
- package/src/components/paywall/PlanOfferingButton.tsx +7 -1
- package/src/components/paywall/PlanPrice.tsx +20 -0
- package/src/components/paywall/index.ts +1 -1
- package/src/components/utils/getPaidPriceText.ts +9 -1
- package/src/components/utils/getPlanPrice.ts +2 -0
- package/src/components/utils/priceTierUtils.ts +60 -14
- package/src/index.ts +9 -1
- package/src/stories/mocks/checkout/mockCheckoutPreview.ts +1 -1
|
@@ -65,6 +65,8 @@ export const PlanPrice = ({
|
|
|
65
65
|
locale,
|
|
66
66
|
hasMonthlyPrice,
|
|
67
67
|
hasAnnuallyPrice,
|
|
68
|
+
perUnitQuantityByFeature,
|
|
69
|
+
setPerUnitQuantityByFeature,
|
|
68
70
|
}: {
|
|
69
71
|
showStartingAt: boolean;
|
|
70
72
|
withUnitPriceRow: boolean;
|
|
@@ -72,6 +74,8 @@ export const PlanPrice = ({
|
|
|
72
74
|
withTiersRow: boolean;
|
|
73
75
|
selectedTierByFeature: Record<string, PriceTierFragment>;
|
|
74
76
|
setSelectedTierByFeature: React.Dispatch<React.SetStateAction<Record<string, PriceTierFragment>>>;
|
|
77
|
+
perUnitQuantityByFeature: Record<string, number>;
|
|
78
|
+
setPerUnitQuantityByFeature: React.Dispatch<React.SetStateAction<Record<string, number>>>;
|
|
75
79
|
plan: PaywallPlan;
|
|
76
80
|
billingPeriod: BillingPeriod;
|
|
77
81
|
paywallLocale: PaywallLocalization;
|
|
@@ -86,6 +90,7 @@ export const PlanPrice = ({
|
|
|
86
90
|
locale,
|
|
87
91
|
hasMonthlyPrice,
|
|
88
92
|
selectedTierByFeature,
|
|
93
|
+
perUnitQuantityByFeature,
|
|
89
94
|
);
|
|
90
95
|
|
|
91
96
|
// We currently only support prices with one tier - so we select the first one
|
|
@@ -94,6 +99,7 @@ export const PlanPrice = ({
|
|
|
94
99
|
});
|
|
95
100
|
const featureId = tieredPrice ? tieredPrice.feature!.featureId : undefined;
|
|
96
101
|
const selectedTier = featureId ? selectedTierByFeature[featureId] : undefined;
|
|
102
|
+
const perUnitQuantity = featureId ? perUnitQuantityByFeature[featureId] : undefined;
|
|
97
103
|
|
|
98
104
|
const handleTierChange = (tier: PriceTierFragment) => {
|
|
99
105
|
if (!featureId) {
|
|
@@ -106,6 +112,17 @@ export const PlanPrice = ({
|
|
|
106
112
|
}));
|
|
107
113
|
};
|
|
108
114
|
|
|
115
|
+
const handlePerUnitQuantityChange = (quantity: number) => {
|
|
116
|
+
if (!featureId) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
setPerUnitQuantityByFeature((prevState) => ({
|
|
121
|
+
...prevState,
|
|
122
|
+
[featureId]: quantity,
|
|
123
|
+
}));
|
|
124
|
+
};
|
|
125
|
+
|
|
109
126
|
return (
|
|
110
127
|
<PlanPriceContainer as="div" className="stigg-price-text">
|
|
111
128
|
<>
|
|
@@ -146,6 +163,9 @@ export const PlanPrice = ({
|
|
|
146
163
|
tierUnits={tierUnits}
|
|
147
164
|
selectedTier={selectedTier}
|
|
148
165
|
handleTierChange={handleTierChange}
|
|
166
|
+
tiersMode={tieredPrice?.tiersMode}
|
|
167
|
+
handlePerUnitQuantityChange={handlePerUnitQuantityChange}
|
|
168
|
+
perUnitQuantity={perUnitQuantity}
|
|
149
169
|
/>
|
|
150
170
|
) : null}
|
|
151
171
|
</>
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { PaywallContainer as Paywall, PaywallContainerProps as PaywallProps } from './PaywallContainer';
|
|
2
|
-
export
|
|
2
|
+
export * from './types';
|
|
3
3
|
export { PaywallLocalization, PlanPriceText, CurrentPlanParams } from './paywallTextOverrides';
|
|
@@ -18,6 +18,7 @@ type GetPaidPriceTextParams = {
|
|
|
18
18
|
shouldShowMonthlyPriceAmount: boolean;
|
|
19
19
|
selectedTierByFeature: Record<string, PriceTierFragment>;
|
|
20
20
|
paywallLocale: PaywallLocalization;
|
|
21
|
+
perUnitQuantityByFeature?: Record<string, number>;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
export function getPaidPriceText({
|
|
@@ -28,6 +29,7 @@ export function getPaidPriceText({
|
|
|
28
29
|
shouldShowMonthlyPriceAmount,
|
|
29
30
|
selectedTierByFeature,
|
|
30
31
|
paywallLocale,
|
|
32
|
+
perUnitQuantityByFeature,
|
|
31
33
|
}: GetPaidPriceTextParams): PlanPriceText {
|
|
32
34
|
const { amount, currency } = paywallCalculatedPrice || planPrices[0];
|
|
33
35
|
const priceAmount = amount || 0;
|
|
@@ -53,7 +55,13 @@ export function getPaidPriceText({
|
|
|
53
55
|
tierUnits = getPriceFeatureUnit(price);
|
|
54
56
|
}
|
|
55
57
|
|
|
56
|
-
priceNumber += calculateTierPrice(
|
|
58
|
+
priceNumber += calculateTierPrice(
|
|
59
|
+
price,
|
|
60
|
+
currentTier,
|
|
61
|
+
selectedBillingPeriod,
|
|
62
|
+
shouldShowMonthlyPriceAmount,
|
|
63
|
+
perUnitQuantityByFeature?.[price.feature!.featureId],
|
|
64
|
+
);
|
|
57
65
|
}
|
|
58
66
|
}
|
|
59
67
|
|
|
@@ -16,6 +16,7 @@ export function getPlanPrice(
|
|
|
16
16
|
locale: string,
|
|
17
17
|
shouldShowMonthlyPriceAmount: boolean,
|
|
18
18
|
selectedTierByFeature?: Record<string, PriceTierFragment>,
|
|
19
|
+
perUnitQuantityByFeature?: Record<string, number>,
|
|
19
20
|
): PlanPriceText {
|
|
20
21
|
switch (plan.pricingType) {
|
|
21
22
|
case PricingType.Free:
|
|
@@ -48,6 +49,7 @@ export function getPlanPrice(
|
|
|
48
49
|
paywallCalculatedPrice,
|
|
49
50
|
selectedBillingPeriod: billingPeriod,
|
|
50
51
|
selectedTierByFeature: selectedTierByFeature || {},
|
|
52
|
+
perUnitQuantityByFeature: perUnitQuantityByFeature || {},
|
|
51
53
|
};
|
|
52
54
|
|
|
53
55
|
return paywallLocale.price.paid
|
|
@@ -14,10 +14,12 @@ export function getTierByQuantity(tiers: PriceTierFragment[], quantity: number)
|
|
|
14
14
|
if (!tiers) return undefined;
|
|
15
15
|
|
|
16
16
|
const ascendingTiers = [...tiers];
|
|
17
|
-
|
|
17
|
+
// Sort tiers by upTo value, ascending, if upTo is not set,
|
|
18
|
+
// put it at the end as it represent the last infinity tier
|
|
19
|
+
ascendingTiers.sort((a, b) => (!a.upTo ? 1 : !b.upTo ? -1 : a.upTo - b.upTo));
|
|
18
20
|
|
|
19
21
|
for (const tier of ascendingTiers) {
|
|
20
|
-
if (quantity <= tier.upTo) {
|
|
22
|
+
if (tier.upTo && quantity <= tier.upTo) {
|
|
21
23
|
return tier;
|
|
22
24
|
}
|
|
23
25
|
}
|
|
@@ -30,21 +32,52 @@ export function calculateTierPrice(
|
|
|
30
32
|
currentTier: PriceTierFragment,
|
|
31
33
|
selectedBillingPeriod: BillingPeriod,
|
|
32
34
|
shouldShowMonthlyPriceAmount: boolean,
|
|
35
|
+
perUnitQuantity?: number,
|
|
33
36
|
): number {
|
|
37
|
+
const unitPrice =
|
|
38
|
+
selectedBillingPeriod === BillingPeriod.Annually && shouldShowMonthlyPriceAmount
|
|
39
|
+
? currentTier.unitPrice.amount / 12
|
|
40
|
+
: currentTier.unitPrice.amount;
|
|
34
41
|
switch (price.tiersMode) {
|
|
35
42
|
case TiersMode.Volume: {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return unitPrice * currentTier.upTo;
|
|
43
|
+
return unitPrice * (currentTier.upTo || 1);
|
|
44
|
+
}
|
|
45
|
+
case TiersMode.VolumePerUnit: {
|
|
46
|
+
return unitPrice * (perUnitQuantity || 1);
|
|
42
47
|
}
|
|
43
48
|
default:
|
|
44
49
|
return 0;
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
52
|
|
|
53
|
+
export function getSelectedTierQuantityBeFeature(
|
|
54
|
+
plan: PaywallPlan,
|
|
55
|
+
billingPeriod: BillingPeriod,
|
|
56
|
+
currentSubscription: Subscription | null,
|
|
57
|
+
) {
|
|
58
|
+
const result: Record<string, number> = {};
|
|
59
|
+
const planTierPrices = plan.pricePoints.filter(
|
|
60
|
+
(price) => price.billingPeriod === billingPeriod && price.isTieredPrice,
|
|
61
|
+
);
|
|
62
|
+
if (planTierPrices.length === 1) {
|
|
63
|
+
const [price] = planTierPrices;
|
|
64
|
+
const featureId = price?.feature!.featureId;
|
|
65
|
+
if (currentSubscription && currentSubscription.plan.id === plan.id) {
|
|
66
|
+
const tieredPrice = currentSubscription?.prices.find(
|
|
67
|
+
(subscriptionPrice) =>
|
|
68
|
+
subscriptionPrice.pricingModel === BillingModel.PerUnit &&
|
|
69
|
+
subscriptionPrice.tiersMode &&
|
|
70
|
+
subscriptionPrice.feature?.featureId === featureId,
|
|
71
|
+
);
|
|
72
|
+
if (tieredPrice) {
|
|
73
|
+
result[featureId] = tieredPrice.feature?.unitQuantity || 1;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
|
|
48
81
|
export function getSelectedTier(
|
|
49
82
|
plan: PaywallPlan,
|
|
50
83
|
billingPeriod: BillingPeriod,
|
|
@@ -64,7 +97,7 @@ export function getSelectedTier(
|
|
|
64
97
|
|
|
65
98
|
if (selectedTierByFeature[featureId]) {
|
|
66
99
|
currentTier = price.tiers?.find((tier) => tier.upTo === selectedTierByFeature[featureId].upTo) || currentTier;
|
|
67
|
-
} else if (currentSubscription) {
|
|
100
|
+
} else if (currentSubscription && currentSubscription.plan.id === plan.id) {
|
|
68
101
|
const tieredPrice = currentSubscription.prices.find(
|
|
69
102
|
(subscriptionPrice) =>
|
|
70
103
|
subscriptionPrice.pricingModel === BillingModel.PerUnit &&
|
|
@@ -94,6 +127,7 @@ export enum PriceTierComparison {
|
|
|
94
127
|
|
|
95
128
|
export function compareSelectedTierToCurrentTier(
|
|
96
129
|
selectedTierByFeature: Record<string, PriceTierFragment>,
|
|
130
|
+
perUnitQuantityByFeature: Record<string, number>,
|
|
97
131
|
currentSubscription: Subscription | null,
|
|
98
132
|
): PriceTierComparison {
|
|
99
133
|
if (!currentSubscription || !selectedTierByFeature) {
|
|
@@ -108,22 +142,34 @@ export function compareSelectedTierToCurrentTier(
|
|
|
108
142
|
}
|
|
109
143
|
|
|
110
144
|
const { featureId, unitQuantity } = currentTierPrice.feature!;
|
|
145
|
+
const { tiersMode } = currentTierPrice;
|
|
111
146
|
|
|
112
147
|
if (!unitQuantity) {
|
|
113
148
|
return PriceTierComparison.Equal;
|
|
114
149
|
}
|
|
115
150
|
|
|
116
151
|
const selectedTier = selectedTierByFeature[featureId];
|
|
152
|
+
const selectedQuantity = perUnitQuantityByFeature[featureId];
|
|
117
153
|
if (!selectedTier) {
|
|
118
154
|
return PriceTierComparison.Equal;
|
|
119
155
|
}
|
|
120
156
|
|
|
121
|
-
if (
|
|
122
|
-
|
|
123
|
-
|
|
157
|
+
if (tiersMode === TiersMode.Volume) {
|
|
158
|
+
if (selectedTier.upTo && selectedTier.upTo < unitQuantity) {
|
|
159
|
+
return PriceTierComparison.Lower;
|
|
160
|
+
}
|
|
124
161
|
|
|
125
|
-
|
|
126
|
-
|
|
162
|
+
if (selectedTier.upTo && selectedTier.upTo > unitQuantity) {
|
|
163
|
+
return PriceTierComparison.Higher;
|
|
164
|
+
}
|
|
165
|
+
} else if (tiersMode === TiersMode.VolumePerUnit) {
|
|
166
|
+
if (selectedQuantity && selectedQuantity < unitQuantity) {
|
|
167
|
+
return PriceTierComparison.Lower;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (selectedQuantity && selectedQuantity > unitQuantity) {
|
|
171
|
+
return PriceTierComparison.Higher;
|
|
172
|
+
}
|
|
127
173
|
}
|
|
128
174
|
|
|
129
175
|
return PriceTierComparison.Equal;
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,9 @@ export {
|
|
|
10
10
|
PaywallLocalization,
|
|
11
11
|
PlanPriceText,
|
|
12
12
|
CurrentPlanParams,
|
|
13
|
+
PaywallData,
|
|
14
|
+
SelectDefaultTierIndexFn,
|
|
15
|
+
ShouldHidePlanFn,
|
|
13
16
|
} from './components/paywall';
|
|
14
17
|
export {
|
|
15
18
|
CustomerPortalProvider,
|
|
@@ -24,6 +27,11 @@ export {
|
|
|
24
27
|
SubscriptionsOverview,
|
|
25
28
|
SubscriptionsOverviewProps,
|
|
26
29
|
Promotions,
|
|
30
|
+
CustomerPortalIntentionType,
|
|
31
|
+
OnBuyMoreCallbackFn,
|
|
32
|
+
OnManageSubscriptionFn,
|
|
33
|
+
CustomerPortalLocalization,
|
|
34
|
+
CustomerPortalTheme,
|
|
27
35
|
} from './components/customerPortal';
|
|
28
36
|
export {
|
|
29
37
|
StiggProvider,
|
|
@@ -49,5 +57,5 @@ export {
|
|
|
49
57
|
TaxDetailsInput,
|
|
50
58
|
} from './components/checkout';
|
|
51
59
|
export { useWaitForCheckoutCompleted, ProvisionStatus } from './components/hooks';
|
|
52
|
-
export { HorizontalAlignment, TextAlignment } from './theme/types';
|
|
60
|
+
export { HorizontalAlignment, TextAlignment, FontVariant, FontWeight, StiggTheme } from './theme/types';
|
|
53
61
|
export { CustomizedTheme as Theme } from './theme/Theme';
|
|
@@ -69,7 +69,7 @@ const billableFeatureCost = (plan: Plan, billingPeriod: BillingPeriod, featureId
|
|
|
69
69
|
const { tiers } = price;
|
|
70
70
|
|
|
71
71
|
if (tiers) {
|
|
72
|
-
const quantityTier = tiers.find((tier) => tier.upTo >= quantity);
|
|
72
|
+
const quantityTier = tiers.find((tier) => tier.upTo && tier.upTo >= quantity);
|
|
73
73
|
const priceTier = quantityTier || tiers[tiers.length - 1];
|
|
74
74
|
return quantity * priceTier.unitPrice.amount;
|
|
75
75
|
}
|