@stigg/react-sdk 4.4.0-beta.9 → 4.4.1

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.
Files changed (92) hide show
  1. package/dist/components/checkout/Checkout.d.ts +3 -2
  2. package/dist/components/checkout/CheckoutContainer.d.ts +4 -2
  3. package/dist/components/checkout/CheckoutProvider.d.ts +3 -2
  4. package/dist/components/checkout/components/DowngradeToFreeContainer.d.ts +3 -7
  5. package/dist/components/checkout/components/StyledArrow.d.ts +5 -0
  6. package/dist/components/checkout/hooks/useCheckoutModel.d.ts +2 -0
  7. package/dist/components/checkout/hooks/useLoadCheckout.d.ts +3 -1
  8. package/dist/components/checkout/hooks/usePreviewSubscription.d.ts +17 -8
  9. package/dist/components/checkout/progressBar/CheckoutProgressBar.style.d.ts +1 -1
  10. package/dist/components/checkout/promotionCode/AddPromotionCode.d.ts +2 -4
  11. package/dist/components/checkout/promotionCode/AddPromotionCodeButton.d.ts +2 -1
  12. package/dist/components/checkout/promotionCode/PromotionCodeSection.d.ts +6 -2
  13. package/dist/components/checkout/steps/plan/BillingPeriodPicker.d.ts +1 -1
  14. package/dist/components/checkout/steps/plan/CheckoutPlanStep.d.ts +2 -1
  15. package/dist/components/checkout/summary/CheckoutSummary.d.ts +1 -1
  16. package/dist/components/checkout/summary/components/CheckoutCaptions.d.ts +2 -2
  17. package/dist/components/checkout/summary/components/LineItems.d.ts +12 -8
  18. package/dist/components/checkout/textOverrides.d.ts +63 -20
  19. package/dist/components/checkout/theme.d.ts +0 -1
  20. package/dist/components/checkout/types.d.ts +7 -1
  21. package/dist/components/common/TiersSelectContainer.d.ts +1 -2
  22. package/dist/components/common/Typography.d.ts +2 -2
  23. package/dist/components/common/customIcons.d.ts +2 -0
  24. package/dist/components/customerPortal/subscriptionOverview/subscriptionView/SubscriptionView.style.d.ts +1 -1
  25. package/dist/components/paywall/PlanPrice.d.ts +1 -1
  26. package/dist/components/utils/currencyUtils.d.ts +2 -1
  27. package/dist/components/utils/getFeatureName.d.ts +1 -0
  28. package/dist/react-sdk.cjs.development.js +1030 -560
  29. package/dist/react-sdk.cjs.development.js.map +1 -1
  30. package/dist/react-sdk.cjs.production.min.js +1 -1
  31. package/dist/react-sdk.cjs.production.min.js.map +1 -1
  32. package/dist/react-sdk.esm.js +1051 -590
  33. package/dist/react-sdk.esm.js.map +1 -1
  34. package/dist/stories/mocks/checkout/consts.d.ts +11 -0
  35. package/dist/stories/mocks/checkout/mockCheckoutPreview.d.ts +2 -0
  36. package/dist/stories/mocks/checkout/mockCheckoutState.d.ts +2 -0
  37. package/dist/theme/getResolvedTheme.d.ts +1 -0
  38. package/dist/theme/types.d.ts +1 -0
  39. package/package.json +28 -20
  40. package/src/assets/coupon.svg +6 -0
  41. package/src/assets/pay-as-you-go-charge.svg +11 -0
  42. package/src/components/checkout/Checkout.tsx +5 -2
  43. package/src/components/checkout/CheckoutContainer.tsx +20 -13
  44. package/src/components/checkout/CheckoutProvider.tsx +5 -3
  45. package/src/components/checkout/components/DowngradeToFreeContainer.tsx +33 -36
  46. package/src/components/checkout/components/InputField.tsx +3 -0
  47. package/src/components/checkout/components/StyledArrow.tsx +9 -0
  48. package/src/components/checkout/hooks/useCheckoutModel.ts +12 -2
  49. package/src/components/checkout/hooks/useLoadCheckout.ts +10 -2
  50. package/src/components/checkout/hooks/usePreviewSubscription.ts +102 -50
  51. package/src/components/checkout/planHeader/PlanHeader.tsx +18 -25
  52. package/src/components/checkout/progressBar/CheckoutProgressBar.style.ts +10 -12
  53. package/src/components/checkout/progressBar/CheckoutProgressBar.tsx +6 -6
  54. package/src/components/checkout/promotionCode/AddPromotionCode.tsx +32 -9
  55. package/src/components/checkout/promotionCode/AddPromotionCodeButton.tsx +15 -11
  56. package/src/components/checkout/promotionCode/AppliedPromotionCode.tsx +4 -3
  57. package/src/components/checkout/promotionCode/PromotionCodeSection.tsx +21 -7
  58. package/src/components/checkout/steps/addons/CheckoutAddonsStep.style.tsx +0 -1
  59. package/src/components/checkout/steps/addons/CheckoutAddonsStep.tsx +4 -3
  60. package/src/components/checkout/steps/payment/PaymentMethods.style.ts +4 -1
  61. package/src/components/checkout/steps/payment/PaymentStep.tsx +0 -1
  62. package/src/components/checkout/steps/plan/BillingPeriodPicker.style.tsx +3 -2
  63. package/src/components/checkout/steps/plan/BillingPeriodPicker.tsx +5 -2
  64. package/src/components/checkout/steps/plan/CheckoutChargeList.tsx +35 -14
  65. package/src/components/checkout/steps/plan/CheckoutPlanStep.tsx +10 -5
  66. package/src/components/checkout/summary/CheckoutSuccess.tsx +1 -1
  67. package/src/components/checkout/summary/CheckoutSummary.tsx +143 -46
  68. package/src/components/checkout/summary/components/CheckoutCaptions.tsx +38 -15
  69. package/src/components/checkout/summary/components/LineItems.tsx +77 -28
  70. package/src/components/checkout/textOverrides.ts +107 -27
  71. package/src/components/checkout/theme.ts +0 -4
  72. package/src/components/checkout/types.ts +15 -1
  73. package/src/components/common/Icon.tsx +4 -6
  74. package/src/components/common/TiersSelectContainer.tsx +7 -8
  75. package/src/components/common/Typography.tsx +12 -3
  76. package/src/components/common/customIcons.ts +2 -0
  77. package/src/components/common/mapExternalTheme.ts +1 -2
  78. package/src/components/customerPortal/paywall/CustomerPortalPaywall.style.ts +4 -3
  79. package/src/components/paywall/PlanOfferingButton.tsx +6 -8
  80. package/src/components/paywall/PlanPrice.tsx +14 -17
  81. package/src/components/utils/currencyUtils.ts +4 -2
  82. package/src/components/utils/getFeatureName.ts +13 -5
  83. package/src/stories/Checkout.stories.tsx +37 -6
  84. package/src/stories/CustomerPortal.stories.tsx +2 -2
  85. package/src/stories/mocks/checkout/consts.ts +15 -0
  86. package/src/stories/mocks/checkout/mockCheckoutPreview.ts +138 -0
  87. package/src/stories/mocks/checkout/mockCheckoutState.ts +206 -0
  88. package/src/theme/Theme.tsx +10 -1
  89. package/src/theme/getResolvedTheme.ts +1 -0
  90. package/src/theme/types.ts +1 -0
  91. package/dist/components/checkout/planHeader/PlanHeader.style.d.ts +0 -25
  92. package/src/components/checkout/planHeader/PlanHeader.style.tsx +0 -23
@@ -1,13 +1,15 @@
1
1
  import React from 'react';
2
2
  import styled from '@emotion/styled/macro';
3
3
  import { Grid } from '@mui/material';
4
- import { BillingPeriod, DiscountType, Price, SubscriptionPreview } from '@stigg/js-client-sdk';
4
+ import { BillingModel, BillingPeriod, Price, SubscriptionPreviewV2 } from '@stigg/js-client-sdk';
5
5
  import { Typography } from '../../../common/Typography';
6
6
  import { currencyPriceFormatter } from '../../../utils/currencyUtils';
7
7
  import { getTierByQuantity } from '../../../utils/priceTierUtils';
8
8
  import { WithSkeleton } from './WithSkeleton';
9
9
  import { Skeleton } from '../../components/Skeletons.style';
10
10
  import { CheckoutLocalization } from '../../textOverrides';
11
+ import { Icon } from '../../../common/Icon';
12
+ import { InformationTooltip } from '../../../common/InformationTooltip';
11
13
 
12
14
  export const LineItemContainer = styled.div`
13
15
  & + & {
@@ -30,15 +32,35 @@ export const getPriceString = ({ amount, price, quantity }: { amount: number; pr
30
32
  billingPeriodString = '12 months';
31
33
  }
32
34
 
33
- const addonPriceFormat = currencyPriceFormatter({ amount, currency: price.currency });
35
+ const addonPriceFormat = currencyPriceFormatter({ amount, currency: price.currency, minimumFractionDigits: 2 });
34
36
 
35
37
  return `${quantity > 1 ? `${quantity} x ${addonPriceFormat} each` : addonPriceFormat}${
36
38
  billingPeriodString ? ` x ${billingPeriodString}` : ''
37
39
  }`;
38
40
  };
39
41
 
40
- export const BilledPriceLineItem = ({ label, quantity, price }: { label: string; quantity: number; price: Price }) => {
42
+ const PayAsYouGoPriceTooltip = ({ checkoutLocalization }: { checkoutLocalization: CheckoutLocalization }) => {
43
+ const title = <Typography variant="body1">{checkoutLocalization.summary.payAsYouGoTooltipText}</Typography>;
44
+ return (
45
+ <InformationTooltip placement="left" title={title}>
46
+ <Icon icon="PayAsYouGoCharge" style={{ display: 'flex' }} />
47
+ </InformationTooltip>
48
+ );
49
+ };
50
+
51
+ export const BilledPriceLineItem = ({
52
+ checkoutLocalization,
53
+ label,
54
+ quantity,
55
+ price,
56
+ }: {
57
+ checkoutLocalization: CheckoutLocalization;
58
+ label: string;
59
+ quantity: number;
60
+ price: Price;
61
+ }) => {
41
62
  const { billingPeriod } = price;
63
+ const isPayAsYouGo = price.pricingModel === BillingModel.UsageBased;
42
64
 
43
65
  let amount;
44
66
  if (price.isTieredPrice) {
@@ -52,7 +74,7 @@ export const BilledPriceLineItem = ({ label, quantity, price }: { label: string;
52
74
  <LineItemContainer>
53
75
  <LineItemRow style={{ alignItems: 'flex-end' }}>
54
76
  <Grid item>
55
- <Typography variant="h6" color="primary">
77
+ <Typography variant="body1" color="secondary">
56
78
  {label}
57
79
  </Typography>
58
80
  {(quantity > 1 || billingPeriod === BillingPeriod.Annually) && (
@@ -61,9 +83,30 @@ export const BilledPriceLineItem = ({ label, quantity, price }: { label: string;
61
83
  </Typography>
62
84
  )}
63
85
  </Grid>
86
+ <Grid item display="flex" gap={1} alignItems="center">
87
+ {isPayAsYouGo && <PayAsYouGoPriceTooltip checkoutLocalization={checkoutLocalization} />}
88
+ <Typography variant="body1" color="secondary" style={{ wordBreak: 'break-word' }}>
89
+ {currencyPriceFormatter({ amount: quantity * amount, currency: price.currency, minimumFractionDigits: 2 })}
90
+ {isPayAsYouGo && ' / unit'}
91
+ </Typography>
92
+ </Grid>
93
+ </LineItemRow>
94
+ </LineItemContainer>
95
+ );
96
+ };
97
+
98
+ export const FreeChargeLineItem = ({ label }: { label: string }) => {
99
+ return (
100
+ <LineItemContainer>
101
+ <LineItemRow style={{ alignItems: 'flex-end' }}>
64
102
  <Grid item>
103
+ <Typography variant="body1" color="secondary">
104
+ {label}
105
+ </Typography>
106
+ </Grid>
107
+ <Grid item display="flex" gap={1} alignItems="center">
65
108
  <Typography variant="body1" color="secondary" style={{ wordBreak: 'break-word' }}>
66
- {currencyPriceFormatter({ amount: quantity * amount, currency: price.currency })}
109
+ Free
67
110
  </Typography>
68
111
  </Grid>
69
112
  </LineItemRow>
@@ -74,33 +117,35 @@ export const BilledPriceLineItem = ({ label, quantity, price }: { label: string;
74
117
  export const DiscountLineItem = ({
75
118
  subscriptionPreview,
76
119
  isFetchingSubscriptionPreview,
120
+ checkoutLocalization,
77
121
  }: {
78
- subscriptionPreview: SubscriptionPreview | null;
122
+ subscriptionPreview: SubscriptionPreviewV2;
79
123
  isFetchingSubscriptionPreview: boolean;
124
+ checkoutLocalization: CheckoutLocalization;
80
125
  }) => {
81
- const { subTotal, discount } = subscriptionPreview || {};
82
- if (!subTotal || !discount) {
126
+ const { discount, discountDetails } = subscriptionPreview.recurringSubscription || {};
127
+ if (!discount || !discountDetails) {
83
128
  return null;
84
129
  }
85
130
 
86
- let discountAmount: number;
87
- if (discount.type === DiscountType.Percentage) {
88
- discountAmount = -1 * Math.abs((discount.value / 100) * subTotal.amount);
89
- } else {
90
- discountAmount = -1 * Math.abs(discount.value);
91
- }
92
-
93
131
  return (
94
132
  <LineItemContainer>
95
133
  <LineItemRow>
96
134
  <Typography variant="body1" color="secondary">
97
- {`Discount${discount.type === DiscountType.Percentage ? ` (${discount.value}% off)` : ''}`}
135
+ {checkoutLocalization.summary.discountText({
136
+ discountDetails,
137
+ currency: subscriptionPreview.total.currency,
138
+ })}
98
139
  </Typography>
99
140
  <Typography variant="body1" color="secondary">
100
141
  {isFetchingSubscriptionPreview ? (
101
142
  <Skeleton width={50} height={16} />
102
143
  ) : (
103
- currencyPriceFormatter({ amount: discountAmount, currency: subTotal.currency })
144
+ currencyPriceFormatter({
145
+ amount: discount.amount,
146
+ currency: discount.currency,
147
+ minimumFractionDigits: 2,
148
+ })
104
149
  )}
105
150
  </Typography>
106
151
  </LineItemRow>
@@ -113,12 +158,13 @@ export const AppliedCreditsLineItem = ({
113
158
  isFetchingSubscriptionPreview,
114
159
  checkoutLocalization,
115
160
  }: {
116
- subscriptionPreview: SubscriptionPreview | null;
161
+ subscriptionPreview: SubscriptionPreviewV2 | null;
117
162
  isFetchingSubscriptionPreview: boolean;
118
163
  checkoutLocalization: CheckoutLocalization;
119
164
  }) => {
120
165
  const { credits } = subscriptionPreview || {};
121
- if (!credits || credits.used.amount <= 0) {
166
+
167
+ if (!credits || !credits.used || credits.used.amount <= 0) {
122
168
  return null;
123
169
  }
124
170
 
@@ -126,11 +172,15 @@ export const AppliedCreditsLineItem = ({
126
172
  <LineItemContainer>
127
173
  <LineItemRow>
128
174
  <Typography variant="body1" color="secondary">
129
- {checkoutLocalization.appliedCreditsTitle}
175
+ {checkoutLocalization.summary.appliedCreditsTitle}
130
176
  </Typography>
131
177
  <Typography variant="body1" color="secondary">
132
178
  <WithSkeleton isLoading={isFetchingSubscriptionPreview}>
133
- {currencyPriceFormatter({ amount: -1 * credits.used.amount, currency: credits.used.currency })}
179
+ {currencyPriceFormatter({
180
+ amount: -1 * credits.used.amount,
181
+ currency: credits.used.currency,
182
+ minimumFractionDigits: 2,
183
+ })}
134
184
  </WithSkeleton>
135
185
  </Typography>
136
186
  </LineItemRow>
@@ -139,16 +189,15 @@ export const AppliedCreditsLineItem = ({
139
189
  };
140
190
 
141
191
  export const TaxLineItem = ({
142
- subscriptionPreview,
192
+ tax,
193
+ taxDetails,
143
194
  isFetchingSubscriptionPreview,
144
195
  checkoutLocalization,
145
196
  }: {
146
- subscriptionPreview: SubscriptionPreview | null;
147
197
  isFetchingSubscriptionPreview: boolean;
148
198
  checkoutLocalization: CheckoutLocalization;
149
- }) => {
150
- const { tax, taxDetails } = subscriptionPreview || {};
151
- if (!taxDetails || !tax) {
199
+ } & Pick<SubscriptionPreviewV2, 'tax' | 'taxDetails'>) => {
200
+ if (!taxDetails || !tax || tax?.amount <= 0) {
152
201
  return null;
153
202
  }
154
203
 
@@ -156,11 +205,11 @@ export const TaxLineItem = ({
156
205
  <LineItemContainer>
157
206
  <LineItemRow>
158
207
  <Typography variant="body1" color="secondary">
159
- {checkoutLocalization.taxTitle({ taxDetails })}
208
+ {checkoutLocalization.summary.taxTitle({ taxDetails })}
160
209
  </Typography>
161
210
  <Typography variant="body1" color="secondary">
162
211
  <WithSkeleton isLoading={isFetchingSubscriptionPreview}>
163
- {currencyPriceFormatter({ amount: tax?.amount, currency: tax?.currency })}
212
+ {currencyPriceFormatter({ amount: tax?.amount, currency: tax?.currency, minimumFractionDigits: 2 })}
164
213
  </WithSkeleton>
165
214
  </Typography>
166
215
  </LineItemRow>
@@ -1,7 +1,15 @@
1
- import { BillingPeriod, Plan, SubscriptionPreviewTaxDetails } from '@stigg/js-client-sdk';
1
+ import {
2
+ BillingPeriod,
3
+ DiscountType,
4
+ Plan,
5
+ SubscriptionPreviewDiscount,
6
+ SubscriptionPreviewTaxDetails,
7
+ DiscountDurationType,
8
+ } from '@stigg/js-client-sdk';
2
9
  import moment from 'moment';
3
10
  import merge from 'lodash/merge';
4
11
  import { DeepPartial } from '../../types';
12
+ import { currencyPriceFormatter } from '../utils/currencyUtils';
5
13
 
6
14
  export type CheckoutLocalization = {
7
15
  changePlan: string;
@@ -10,55 +18,127 @@ export type CheckoutLocalization = {
10
18
  newPaymentMethodText: string;
11
19
  newPaymentMethodCardTitle: string;
12
20
  newPaymentMethodBillingAddressTitle: string;
13
- baseChargeText: string | ((params: { billingPeriod: BillingPeriod }) => string);
14
- totalText: string;
15
- subTotalText: string;
16
- addCouponCodeText: string;
17
- couponCodeTitle: string;
18
- addonsSectionTitle: string;
19
- changesWillApplyAtEndOfBillingPeriod: string | ((params: { billingPeriodEnd: Date }) => string);
21
+ summary: {
22
+ title: string;
23
+ planName: (params: { plan: Plan }) => string;
24
+ addCouponCodeText: string;
25
+ couponCodeTitle: string;
26
+ addonsSectionTitle: string;
27
+ discountsSectionTitle: string;
28
+ onlyPayAsYouGoText: string;
29
+ startsAtText: string;
30
+ proratedTotalDueText: string;
31
+ baseChargeText: string | ((params: { billingPeriod: BillingPeriod }) => string);
32
+ totalText: string;
33
+ totalDueText: string;
34
+ totalBillingPeriodText: (params: { billingPeriod: BillingPeriod }) => string;
35
+ discountText: (params: { discountDetails: SubscriptionPreviewDiscount; currency: string }) => string;
36
+ appliedCreditsTitle: string;
37
+ taxTitle: (params: { taxDetails: SubscriptionPreviewTaxDetails }) => string;
38
+ checkoutSuccessText: string;
39
+ payAsYouGoTooltipText: string;
40
+ changesWillApplyAtEndOfBillingPeriod: string | ((params: { billingPeriodEnd: Date }) => string);
41
+ creditsForUnusedTimeText: (params: { credits: string }) => string;
42
+ };
20
43
  checkoutButton: {
21
44
  nextText: string;
45
+ noChangesText: string;
22
46
  updateText: string;
23
47
  downgradeToFreeText: string;
24
48
  upgradeText: string;
25
49
  };
26
- appliedCreditsTitle: string;
27
- taxTitle: (params: { taxDetails: SubscriptionPreviewTaxDetails }) => string;
28
- downgradeToFreeAlertText: (params: { plan: Plan }) => string;
29
- checkoutSuccessText: string;
50
+ downgradeToFree: {
51
+ alertText: (params: { plan: Plan }) => string;
52
+ freePlanHeader: (params: { plan: Plan }) => string;
53
+ freePlanName: (params: { plan: Plan }) => string;
54
+ freePlanPriceText: (params: { plan: Plan }) => string;
55
+ paidPlanHeader: (params: { plan: Plan }) => string;
56
+ paidPlanName: (params: { plan: Plan }) => string;
57
+ paidPlanPriceText: (params: { plan: Plan; billingPeriod?: BillingPeriod }) => string;
58
+ };
30
59
  };
31
60
 
32
61
  export function getResolvedCheckoutLocalize(
33
62
  localizeOverride?: DeepPartial<CheckoutLocalization>,
34
63
  ): CheckoutLocalization {
35
64
  const checkoutDefaultLocalization: CheckoutLocalization = {
36
- changePlan: 'Change plan',
65
+ changePlan: 'Change',
37
66
  billingPeriodsTitle: 'Billing cycle',
38
67
  addAddonText: 'Add',
39
68
  newPaymentMethodText: 'New payment method',
40
69
  newPaymentMethodBillingAddressTitle: 'Billing address',
41
70
  newPaymentMethodCardTitle: 'Payment method',
42
- baseChargeText: () => 'Base charge',
43
- totalText: 'Total due today',
44
- subTotalText: 'Subtotal',
45
- addCouponCodeText: 'Add promotion code',
46
- couponCodeTitle: 'Promotion code',
47
- addonsSectionTitle: 'Add-ons',
48
- changesWillApplyAtEndOfBillingPeriod: ({ billingPeriodEnd }) =>
49
- `Your changes will be applied at the end of your billing cycle on ${moment(billingPeriodEnd).format(
50
- 'MMM D, YYYY',
51
- )}.`,
71
+ summary: {
72
+ title: 'Order summary',
73
+ planName: ({ plan }) => `${plan.displayName} plan`,
74
+ addCouponCodeText: 'Add promotion code',
75
+ couponCodeTitle: 'Promotion code',
76
+ addonsSectionTitle: 'Add-ons',
77
+ discountsSectionTitle: 'Discounts',
78
+ onlyPayAsYouGoText: 'Varies by usage',
79
+ startsAtText: 'Starts at ',
80
+ proratedTotalDueText: 'Prorated charge today',
81
+ baseChargeText: () => 'Base charge',
82
+ totalText: 'Total',
83
+ totalDueText: 'Total due today',
84
+ totalBillingPeriodText: ({ billingPeriod }) => `Billed ${billingPeriod.toLowerCase()}`,
85
+ appliedCreditsTitle: 'Applied credits',
86
+ creditsForUnusedTimeText: ({ credits }) =>
87
+ `Your account will be granted credits worth ${credits} for unused time, which will be automatically applied to future payments.`,
88
+ discountText: ({ discountDetails, currency }) => {
89
+ let discountText = '';
90
+ if (discountDetails.type === DiscountType.Percentage) {
91
+ discountText = `${discountDetails.value}% off`;
92
+ } else {
93
+ discountText = `${currencyPriceFormatter({ amount: discountDetails.value, currency })}`;
94
+ }
95
+
96
+ let discountTextPostfix = '';
97
+ switch (discountDetails.durationType) {
98
+ case DiscountDurationType.Once: {
99
+ discountTextPostfix = ' once';
100
+ break;
101
+ }
102
+ case DiscountDurationType.Repeating: {
103
+ const prefix = discountDetails.type === DiscountType.Fixed ? ' per month' : '';
104
+ discountTextPostfix = `${prefix} for ${discountDetails.durationInMonths} months`;
105
+
106
+ break;
107
+ }
108
+
109
+ case DiscountDurationType.Forever:
110
+ default: {
111
+ discountTextPostfix = '';
112
+ }
113
+ }
114
+
115
+ return `${discountText}${discountTextPostfix}`;
116
+ },
117
+ taxTitle: ({ taxDetails }) => `Tax (${taxDetails?.percentage}%)`,
118
+ changesWillApplyAtEndOfBillingPeriod: ({ billingPeriodEnd }) =>
119
+ `Your changes will take effect at the end of your current billing cycle on ${moment(billingPeriodEnd).format(
120
+ 'MMMM D, YYYY',
121
+ )}.`,
122
+ checkoutSuccessText: 'Changes applied',
123
+ payAsYouGoTooltipText: 'Billed according to actual usage',
124
+ },
52
125
  checkoutButton: {
53
126
  nextText: 'Next',
127
+ noChangesText: 'No changes',
54
128
  updateText: 'Update subscription',
55
129
  downgradeToFreeText: 'Cancel subscription',
56
130
  upgradeText: 'Subscribe',
57
131
  },
58
- appliedCreditsTitle: 'Applied credits',
59
- taxTitle: ({ taxDetails }) => `Tax (${taxDetails?.percentage}%)`,
60
- downgradeToFreeAlertText: () => `We’re sorry to see you cancel your paid subscription 😭`,
61
- checkoutSuccessText: 'Payment successful',
132
+ downgradeToFree: {
133
+ alertText: () => `We’re sorry to see you cancel your paid subscription 😭`,
134
+ freePlanHeader: () => 'New plan',
135
+ freePlanName: ({ plan }) => `${plan.displayName}`,
136
+ freePlanPriceText: () => 'Free',
137
+ paidPlanHeader: () => 'Current plan',
138
+ paidPlanName: ({ plan }) => `${plan.displayName}`,
139
+ paidPlanPriceText: ({ billingPeriod }) =>
140
+ `Paid plan${billingPeriod ? `, billed ${billingPeriod.toLowerCase()}` : ''}`,
141
+ },
62
142
  };
63
143
 
64
144
  return merge(checkoutDefaultLocalization, localizeOverride);
@@ -7,7 +7,6 @@ export type CheckoutTheme = {
7
7
  textColor: string;
8
8
  backgroundColor: string;
9
9
  borderColor: string;
10
- selectionColor: string;
11
10
  summaryBackgroundColor: string;
12
11
  };
13
12
 
@@ -16,7 +15,6 @@ const defaultCheckoutTheme: CheckoutTheme = {
16
15
  textColor: 'rgb(0, 30, 108)',
17
16
  backgroundColor: 'rgb(255, 255, 255)',
18
17
  borderColor: 'rgb(235, 237, 243)',
19
- selectionColor: 'rgb(229, 242, 255)',
20
18
  summaryBackgroundColor: 'rgb(109, 121, 144)',
21
19
  };
22
20
 
@@ -33,8 +31,6 @@ export function getResolvedCheckoutTheme(
33
31
  backgroundColor:
34
32
  themeOverride?.backgroundColor || globalPalette?.backgroundPaper || defaultCheckoutTheme.backgroundColor,
35
33
  borderColor: themeOverride?.borderColor || globalPalette?.outlinedBorder || defaultCheckoutTheme.borderColor,
36
- selectionColor:
37
- themeOverride?.selectionColor || globalPalette?.backgroundSection || defaultCheckoutTheme.selectionColor,
38
34
  summaryBackgroundColor:
39
35
  themeOverride?.summaryBackgroundColor ||
40
36
  globalPalette?.backgroundHighlight ||
@@ -1,4 +1,10 @@
1
- import { SubscriptionBillingInfo } from '@stigg/js-client-sdk';
1
+ import {
2
+ GetCheckoutState,
3
+ GetCheckoutStateResults,
4
+ PreviewSubscription,
5
+ SubscriptionBillingInfo,
6
+ SubscriptionPreviewV2,
7
+ } from '@stigg/js-client-sdk';
2
8
 
3
9
  export type BillingInformation = {
4
10
  taxDetails?: TaxDetailsInput;
@@ -7,3 +13,11 @@ export type BillingInformation = {
7
13
  export type TaxDetailsInput = {
8
14
  taxPercentage?: SubscriptionBillingInfo['taxPercentage'];
9
15
  };
16
+
17
+ export type MockCheckoutPreviewCallback = (params: PreviewSubscription) => SubscriptionPreviewV2;
18
+ export type MockCheckoutStateCallback = (params: GetCheckoutState) => GetCheckoutStateResults;
19
+
20
+ export type CheckoutMockProps = {
21
+ onMockCheckoutPreview?: MockCheckoutPreviewCallback;
22
+ onMockCheckoutState?: MockCheckoutStateCallback;
23
+ };
@@ -1,7 +1,6 @@
1
- import React from 'react';
2
1
  import styled from '@emotion/styled/macro';
3
- import { CSSProperties } from 'react';
4
- import { css, Theme, useTheme } from '@emotion/react';
2
+ import React, { CSSProperties } from 'react';
3
+ import { css, useTheme } from '@emotion/react';
5
4
  import { getIconColor, IconColor } from './iconColor';
6
5
  import * as customIcons from './customIcons';
7
6
 
@@ -45,7 +44,7 @@ export type IconProps = {
45
44
 
46
45
  export function Icon({ icon, className, style, svgPathColor, svgRectColor, svgStrokeColor }: IconProps) {
47
46
  const IconComponent = (customIcons as any)[icon];
48
- const theme = useTheme() as Theme;
47
+ const theme = useTheme();
49
48
 
50
49
  return (
51
50
  <IconWrapper
@@ -53,8 +52,7 @@ export function Icon({ icon, className, style, svgPathColor, svgRectColor, svgSt
53
52
  style={style}
54
53
  $pathColor={getIconColor(svgPathColor, theme)}
55
54
  $rectColor={getIconColor(svgRectColor, theme)}
56
- $strokeColor={getIconColor(svgStrokeColor, theme)}
57
- >
55
+ $strokeColor={getIconColor(svgStrokeColor, theme)}>
58
56
  <IconComponent />
59
57
  </IconWrapper>
60
58
  );
@@ -1,13 +1,15 @@
1
1
  import { PriceTierFragment } from '@stigg/js-client-sdk';
2
2
  import { MenuItem, OutlinedInput, Select, SelectChangeEvent } from '@mui/material';
3
- import { Typography } from '../common/Typography';
4
3
  import { map } from 'lodash';
5
4
  import React, { ReactNode } from 'react';
6
5
  import styled from '@emotion/styled/macro';
7
6
  import { getTierByQuantity } from '../utils/priceTierUtils';
7
+ import { Typography } from './Typography';
8
8
 
9
9
  const TierSelect = styled(Select)`
10
10
  border-radius: 10px;
11
+ min-height: 42px;
12
+ min-width: 120px;
11
13
 
12
14
  &:hover .MuiOutlinedInput-notchedOutline {
13
15
  border-color: ${({ theme }) => theme.stigg.palette.outlinedBorder};
@@ -16,7 +18,7 @@ const TierSelect = styled(Select)`
16
18
 
17
19
  const TierInput = styled(OutlinedInput)`
18
20
  & .MuiInputBase-input {
19
- padding: 7px 12px;
21
+ padding: 10px 12px;
20
22
  }
21
23
 
22
24
  &.Mui-focused .MuiOutlinedInput-notchedOutline {
@@ -27,13 +29,11 @@ const TierInput = styled(OutlinedInput)`
27
29
  export function TiersSelectContainer({
28
30
  componentId,
29
31
  tiers,
30
- tierUnits,
31
32
  selectedTier,
32
33
  handleTierChange,
33
34
  }: {
34
35
  componentId: string;
35
36
  tiers?: PriceTierFragment[] | null;
36
- tierUnits?: string;
37
37
  selectedTier?: PriceTierFragment;
38
38
  handleTierChange: (tier: PriceTierFragment) => void;
39
39
  }) {
@@ -57,12 +57,11 @@ export function TiersSelectContainer({
57
57
  PaperProps: {
58
58
  sx: { marginTop: '4px', borderRadius: '10px' },
59
59
  },
60
- }}
61
- >
60
+ }}>
62
61
  {map(tiers, (tier: PriceTierFragment) => (
63
62
  <MenuItem className="stigg-price-tier-menu-item-text" key={tier.upTo} value={tier.upTo.toString()}>
64
- <Typography variant="body1" color="primary">
65
- {tier.upTo} {tierUnits}
63
+ <Typography variant="body1" color="primary" style={{ lineHeight: 'unset' }}>
64
+ {tier.upTo}
66
65
  </Typography>
67
66
  </MenuItem>
68
67
  ))}
@@ -4,7 +4,15 @@ import { FontWeight as StyledFontWeight, Text, TypeProps } from 'styled-typograp
4
4
  import { Theme, useTheme } from '@emotion/react';
5
5
  import { FontWeight } from '../../theme/types';
6
6
 
7
- type Colors = 'primary' | 'primary.main' | 'secondary' | 'disabled' | 'white' | 'warning' | 'error';
7
+ type Colors =
8
+ | 'primary'
9
+ | 'primary.main'
10
+ | 'primary.main.light'
11
+ | 'secondary'
12
+ | 'disabled'
13
+ | 'white'
14
+ | 'warning'
15
+ | 'error';
8
16
 
9
17
  export type TypographyProps = {
10
18
  children: React.ReactNode;
@@ -25,6 +33,8 @@ function getColor(theme: Theme, $color: Colors) {
25
33
  return 'white';
26
34
  case 'primary.main':
27
35
  return theme.stigg.palette.primary;
36
+ case 'primary.main.light':
37
+ return theme.stigg.palette.primaryLight;
28
38
  case 'warning':
29
39
  return theme.stigg.palette.warning;
30
40
  case 'error':
@@ -111,8 +121,7 @@ export const Typography = forwardRef((props: TypographyProps, ref) => {
111
121
  level={level}
112
122
  color={overrideColor || getColor(theme, color)}
113
123
  fontWeight={fontWeight ?? (bold ? StyledFontWeight.Bold : getFontWeight(theme, variant))}
114
- $span={span}
115
- >
124
+ $span={span}>
116
125
  {children}
117
126
  </StyledText>
118
127
  );
@@ -17,3 +17,5 @@ export { default as OutlinedCheckedCircleDisabled } from '../../assets/outlined-
17
17
  export { default as ArrowForward } from '../../assets/arrow-forward.svg';
18
18
  export { default as Close } from '../../assets/close.svg';
19
19
  export { default as Check } from '../../assets/check.svg';
20
+ export { default as PayAsYouGoCharge } from '../../assets/pay-as-you-go-charge.svg';
21
+ export { default as Coupon } from '../../assets/coupon.svg';
@@ -123,8 +123,7 @@ export function mapCheckoutConfiguration(configuration: CheckoutConfiguration):
123
123
  text: {
124
124
  primary: palette?.textColor || undefined,
125
125
  },
126
- backgroundHighlight: palette?.selectionColor || undefined,
127
- backgroundSection: palette?.summaryBackgroundColor || undefined,
126
+ backgroundHighlight: palette?.summaryBackgroundColor || undefined,
128
127
  },
129
128
  typography: mapTypography(typography),
130
129
  };
@@ -13,14 +13,15 @@ export const CustomerPortalPaywallLayout = styled(SectionContainer)<{
13
13
  .stigg-paywall-layout {
14
14
  width: 100%;
15
15
  }
16
-
16
+
17
17
  .stigg-paywall-plans-layout {
18
18
  flex-wrap: nowrap;
19
19
  width: 100%;
20
20
  overflow-x: auto;
21
21
  justify-content: unset;
22
- padding: 0;
22
+ padding: 10px 0px 0px 0px;
23
23
  }
24
+
24
25
  .stigg-paywall-plans-layout .stigg-plan-offering-container:first-of-type {
25
26
  margin-left: auto;
26
27
  }
@@ -37,6 +38,6 @@ export const CustomerPortalPaywallLayout = styled(SectionContainer)<{
37
38
  `}
38
39
 
39
40
  .${STIGG_WATERMARK_CLASSNAME} {
40
- display: none
41
+ display: none;
41
42
  }
42
43
  `;
@@ -1,14 +1,14 @@
1
1
  import React, { useState } from 'react';
2
2
  import { BillingPeriod, Customer, PriceTierFragment, PricingType, Subscription } from '@stigg/js-client-sdk';
3
+ import { isFunction } from 'lodash';
4
+ import ClipLoader from 'react-spinners/ClipLoader';
3
5
  import styled from '@emotion/styled/macro';
4
- import { css, Theme, useTheme } from '@emotion/react';
6
+ import { css, useTheme } from '@emotion/react';
5
7
  import { PaywallPlan, SubscribeIntentionType } from './types';
6
8
  import { PaywallLocalization } from './paywallTextOverrides';
7
9
  import { flexLayoutMapper } from '../../theme/getResolvedTheme';
8
- import ClipLoader from 'react-spinners/ClipLoader';
9
10
  import { Typography } from '../common/Typography';
10
11
  import { getSubscriptionScheduleUpdateTexts } from '../utils/getSubscriptionScheduleUpdateTexts';
11
- import { isFunction } from 'lodash';
12
12
  import { compareSelectedTierToCurrentTier, PriceTierComparison } from '../utils/priceTierUtils';
13
13
 
14
14
  const LoadingIndicator = styled(ClipLoader)`
@@ -99,7 +99,7 @@ export function PlanOfferingButton({
99
99
  currentSubscription,
100
100
  selectedTierByFeature,
101
101
  }: PlanOfferingButtonProps) {
102
- const theme = useTheme() as Theme;
102
+ const theme = useTheme();
103
103
  const [isLoading, setIsLoading] = useState(false);
104
104
  const {
105
105
  currentPlan,
@@ -187,8 +187,7 @@ export function PlanOfferingButton({
187
187
  onClick={() => {
188
188
  setIsLoading(true);
189
189
  Promise.resolve(onPlanSelected(buttonProps.intentionType)).finally(() => setIsLoading(false));
190
- }}
191
- >
190
+ }}>
192
191
  {buttonProps.title}
193
192
  </CancelScheduledUpdateButton>
194
193
  </ScheduledUpdateText>
@@ -202,8 +201,7 @@ export function PlanOfferingButton({
202
201
  onClick={() => {
203
202
  setIsLoading(true);
204
203
  Promise.resolve(onPlanSelected(buttonProps.intentionType)).finally(() => setIsLoading(false));
205
- }}
206
- >
204
+ }}>
207
205
  <ButtonText className="stigg-paywall-plan-button-text" variant="h6" color="primary.main">
208
206
  {buttonProps.title}
209
207
  </ButtonText>