@stigg/react-sdk 4.2.3 → 4.3.0-beta.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 (164) hide show
  1. package/README.md +1 -1
  2. package/dist/components/checkout/Checkout.d.ts +5 -0
  3. package/dist/components/checkout/CheckoutContainer.d.ts +22 -0
  4. package/dist/components/checkout/CheckoutContainer.style.d.ts +26 -0
  5. package/dist/components/checkout/CheckoutProvider.d.ts +35 -0
  6. package/dist/components/checkout/CheckoutSummary.d.ts +9 -0
  7. package/dist/components/checkout/components/Button.d.ts +6 -0
  8. package/dist/components/checkout/components/InputField.d.ts +8 -0
  9. package/dist/components/checkout/components/index.d.ts +2 -0
  10. package/dist/components/checkout/formatting.d.ts +2 -0
  11. package/dist/components/checkout/hooks/index.d.ts +8 -0
  12. package/dist/components/checkout/hooks/useAddonsStepModel.d.ts +21 -0
  13. package/dist/components/checkout/hooks/useCheckoutModel.d.ts +9 -0
  14. package/dist/components/checkout/hooks/useCouponModel.d.ts +7 -0
  15. package/dist/components/checkout/hooks/useLoadCheckout.d.ts +11 -0
  16. package/dist/components/checkout/hooks/usePaymentStepModel.d.ts +16 -0
  17. package/dist/components/checkout/hooks/usePlanStepModel.d.ts +23 -0
  18. package/dist/components/checkout/hooks/usePreviewSubscription.d.ts +13 -0
  19. package/dist/components/checkout/hooks/useProgressBarModel.d.ts +26 -0
  20. package/dist/components/checkout/hooks/useSubscriptionModel.d.ts +5 -0
  21. package/dist/components/checkout/hooks/useSubscriptionState.d.ts +2 -0
  22. package/dist/components/checkout/index.d.ts +3 -0
  23. package/dist/components/checkout/planHeader/PlanHeader.d.ts +7 -0
  24. package/dist/components/checkout/planHeader/PlanHeader.style.d.ts +25 -0
  25. package/dist/components/checkout/planHeader/index.d.ts +1 -0
  26. package/dist/components/checkout/progressBar/CheckoutProgressBar.d.ts +2 -0
  27. package/dist/components/checkout/progressBar/CheckoutProgressBar.style.d.ts +45 -0
  28. package/dist/components/checkout/promotionCode/AddPromotionCode.d.ts +5 -0
  29. package/dist/components/checkout/promotionCode/AddPromotionCodeButton.d.ts +7 -0
  30. package/dist/components/checkout/promotionCode/AppliedPromotionCode.d.ts +6 -0
  31. package/dist/components/checkout/promotionCode/PromotionCodeSection.d.ts +5 -0
  32. package/dist/components/checkout/promotionCode/index.d.ts +1 -0
  33. package/dist/components/checkout/steps/addons/CheckoutAddonsStep.d.ts +2 -0
  34. package/dist/components/checkout/steps/addons/CheckoutAddonsStep.style.d.ts +93 -0
  35. package/dist/components/checkout/steps/addons/addon.utils.d.ts +15 -0
  36. package/dist/components/checkout/steps/addons/index.d.ts +1 -0
  37. package/dist/components/checkout/steps/payment/PaymentMethods.d.ts +19 -0
  38. package/dist/components/checkout/steps/payment/PaymentMethods.style.d.ts +113 -0
  39. package/dist/components/checkout/steps/payment/PaymentStep.d.ts +2 -0
  40. package/dist/components/checkout/steps/payment/index.d.ts +1 -0
  41. package/dist/components/checkout/steps/payment/stripe/StripePaymentForm.d.ts +2 -0
  42. package/dist/components/checkout/steps/payment/stripe/index.d.ts +3 -0
  43. package/dist/components/checkout/steps/payment/stripe/stripe.utils.d.ts +33 -0
  44. package/dist/components/checkout/steps/payment/stripe/useStripeIntegration.d.ts +5 -0
  45. package/dist/components/checkout/steps/payment/stripe/useSubmit.d.ts +10 -0
  46. package/dist/components/checkout/steps/plan/BillingPeriodPicker.d.ts +9 -0
  47. package/dist/components/checkout/steps/plan/BillingPeriodPicker.style.d.ts +52 -0
  48. package/dist/components/checkout/steps/plan/CheckoutChargeList.d.ts +16 -0
  49. package/dist/components/checkout/steps/plan/CheckoutPlanStep.d.ts +4 -0
  50. package/dist/components/checkout/steps/plan/CheckoutPlanStep.style.d.ts +12 -0
  51. package/dist/components/checkout/steps/plan/index.d.ts +1 -0
  52. package/dist/components/checkout/steps/surprise/SurpriseStep.d.ts +2 -0
  53. package/dist/components/checkout/textOverrides.d.ts +28 -0
  54. package/dist/components/checkout/theme.d.ts +12 -0
  55. package/dist/components/common/Icon.d.ts +3 -2
  56. package/dist/components/common/PoweredByStigg.d.ts +1 -1
  57. package/dist/components/{paywall/TiersLayout.d.ts → common/TiersSelectContainer.d.ts} +2 -3
  58. package/dist/components/common/customIcons.d.ts +17 -5
  59. package/dist/components/common/mapExternalTheme.d.ts +2 -1
  60. package/dist/components/customerPortal/subscriptionOverview/tabs/SubscriptionTabs.d.ts +1 -1
  61. package/dist/components/hooks/useChargeSort.d.ts +3 -0
  62. package/dist/components/utils/calculateDiscountRate.d.ts +1 -0
  63. package/dist/components/utils/currencyUtils.d.ts +1 -1
  64. package/dist/components/{paywall/planPriceTier.d.ts → utils/priceTierUtils.d.ts} +3 -1
  65. package/dist/components/utils/priceUtils.d.ts +2 -0
  66. package/dist/index.d.ts +1 -0
  67. package/dist/react-sdk.cjs.development.js +3476 -201
  68. package/dist/react-sdk.cjs.development.js.map +1 -1
  69. package/dist/react-sdk.cjs.production.min.js +1 -1
  70. package/dist/react-sdk.cjs.production.min.js.map +1 -1
  71. package/dist/react-sdk.esm.js +3616 -207
  72. package/dist/react-sdk.esm.js.map +1 -1
  73. package/dist/stories/Checkout.stories.d.ts +3 -0
  74. package/dist/stories/CustomerPortal.stories.d.ts +1 -1
  75. package/dist/theme/getResolvedTheme.d.ts +1 -0
  76. package/dist/theme/types.d.ts +1 -0
  77. package/package.json +7 -4
  78. package/src/assets/arrow-forward.svg +3 -0
  79. package/src/assets/arrow-right.svg +6 -0
  80. package/src/assets/close.svg +3 -0
  81. package/src/assets/nyancat.svg +634 -0
  82. package/src/assets/outlined-checked-circle.svg +6 -0
  83. package/src/assets/outlined-circle.svg +3 -0
  84. package/src/assets/payment-method.svg +11 -0
  85. package/src/assets/plus-icon.svg +6 -0
  86. package/src/assets/trash.svg +8 -0
  87. package/src/components/StiggProvider.tsx +5 -5
  88. package/src/components/checkout/Checkout.tsx +30 -0
  89. package/src/components/checkout/CheckoutContainer.style.ts +34 -0
  90. package/src/components/checkout/CheckoutContainer.tsx +88 -0
  91. package/src/components/checkout/CheckoutProvider.tsx +140 -0
  92. package/src/components/checkout/CheckoutSummary.tsx +361 -0
  93. package/src/components/checkout/components/Button.tsx +30 -0
  94. package/src/components/checkout/components/InputField.tsx +22 -0
  95. package/src/components/checkout/components/index.ts +2 -0
  96. package/src/components/checkout/formatting.ts +12 -0
  97. package/src/components/checkout/hooks/index.ts +8 -0
  98. package/src/components/checkout/hooks/useAddonsStepModel.ts +96 -0
  99. package/src/components/checkout/hooks/useCheckoutModel.ts +31 -0
  100. package/src/components/checkout/hooks/useCouponModel.ts +28 -0
  101. package/src/components/checkout/hooks/useLoadCheckout.ts +40 -0
  102. package/src/components/checkout/hooks/usePaymentStepModel.ts +49 -0
  103. package/src/components/checkout/hooks/usePlanStepModel.ts +170 -0
  104. package/src/components/checkout/hooks/usePreviewSubscription.ts +82 -0
  105. package/src/components/checkout/hooks/useProgressBarModel.ts +89 -0
  106. package/src/components/checkout/hooks/useSubscriptionModel.ts +16 -0
  107. package/src/components/checkout/hooks/useSubscriptionState.ts +26 -0
  108. package/src/components/checkout/index.ts +3 -0
  109. package/src/components/checkout/planHeader/PlanHeader.style.tsx +23 -0
  110. package/src/components/checkout/planHeader/PlanHeader.tsx +61 -0
  111. package/src/components/checkout/planHeader/index.ts +1 -0
  112. package/src/components/checkout/progressBar/CheckoutProgressBar.style.ts +29 -0
  113. package/src/components/checkout/progressBar/CheckoutProgressBar.tsx +48 -0
  114. package/src/components/checkout/promotionCode/AddPromotionCode.tsx +85 -0
  115. package/src/components/checkout/promotionCode/AddPromotionCodeButton.tsx +39 -0
  116. package/src/components/checkout/promotionCode/AppliedPromotionCode.tsx +37 -0
  117. package/src/components/checkout/promotionCode/PromotionCodeSection.tsx +27 -0
  118. package/src/components/checkout/promotionCode/index.ts +1 -0
  119. package/src/components/checkout/steps/addons/CheckoutAddonsStep.style.tsx +24 -0
  120. package/src/components/checkout/steps/addons/CheckoutAddonsStep.tsx +125 -0
  121. package/src/components/checkout/steps/addons/addon.utils.ts +68 -0
  122. package/src/components/checkout/steps/addons/index.ts +1 -0
  123. package/src/components/checkout/steps/payment/PaymentMethods.style.ts +26 -0
  124. package/src/components/checkout/steps/payment/PaymentMethods.tsx +83 -0
  125. package/src/components/checkout/steps/payment/PaymentStep.tsx +41 -0
  126. package/src/components/checkout/steps/payment/index.ts +1 -0
  127. package/src/components/checkout/steps/payment/stripe/StripePaymentForm.tsx +43 -0
  128. package/src/components/checkout/steps/payment/stripe/index.ts +3 -0
  129. package/src/components/checkout/steps/payment/stripe/stripe.utils.ts +109 -0
  130. package/src/components/checkout/steps/payment/stripe/useStripeIntegration.ts +27 -0
  131. package/src/components/checkout/steps/payment/stripe/useSubmit.ts +100 -0
  132. package/src/components/checkout/steps/plan/BillingPeriodPicker.style.tsx +46 -0
  133. package/src/components/checkout/steps/plan/BillingPeriodPicker.tsx +63 -0
  134. package/src/components/checkout/steps/plan/CheckoutChargeList.tsx +138 -0
  135. package/src/components/checkout/steps/plan/CheckoutPlanStep.style.tsx +6 -0
  136. package/src/components/checkout/steps/plan/CheckoutPlanStep.tsx +22 -0
  137. package/src/components/checkout/steps/plan/index.ts +1 -0
  138. package/src/components/checkout/steps/surprise/SurpriseStep.tsx +27 -0
  139. package/src/components/checkout/textOverrides.ts +58 -0
  140. package/src/components/checkout/theme.ts +43 -0
  141. package/src/components/common/Icon.tsx +17 -22
  142. package/src/components/common/PoweredByStigg.tsx +1 -1
  143. package/src/components/{paywall/TiersLayout.tsx → common/TiersSelectContainer.tsx} +8 -7
  144. package/src/components/common/Typography.tsx +11 -1
  145. package/src/components/common/customIcons.ts +17 -28
  146. package/src/components/common/mapExternalTheme.ts +24 -8
  147. package/src/components/customerPortal/subscriptionOverview/tabs/SubscriptionTabs.tsx +6 -12
  148. package/src/components/hooks/useChargeSort.ts +17 -0
  149. package/src/components/paywall/Paywall.tsx +1 -1
  150. package/src/components/paywall/PlanOffering.tsx +1 -1
  151. package/src/components/paywall/PlanOfferingButton.tsx +1 -1
  152. package/src/components/paywall/PlanPrice.tsx +3 -3
  153. package/src/components/paywall/utils/calculateUnitQuantityText.ts +9 -4
  154. package/src/components/utils/calculateDiscountRate.ts +1 -1
  155. package/src/components/utils/currencyUtils.ts +1 -1
  156. package/src/components/utils/getPaidPriceText.ts +2 -2
  157. package/src/components/{paywall/planPriceTier.ts → utils/priceTierUtils.ts} +25 -3
  158. package/src/components/utils/priceUtils.ts +10 -0
  159. package/src/index.ts +1 -0
  160. package/src/stories/Checkout.stories.tsx +62 -0
  161. package/src/stories/CustomerPortal.stories.tsx +1 -1
  162. package/src/theme/Theme.tsx +9 -8
  163. package/src/theme/getResolvedTheme.ts +1 -0
  164. package/src/theme/types.ts +1 -0
@@ -1,28 +1,17 @@
1
- import { ReactElement, SVGProps } from 'react';
2
- import RenewSubscription from '../../assets/subscription-renews-icon.svg';
3
- import BillingInfoCustomer from '../../assets/billing-info-customer.svg';
4
- import CreditCard from '../../assets/credit-card.svg';
5
- import ScheduleBox from '../../assets/schedule-box.svg';
6
- import ScheduleClock from '../../assets/schedule.svg';
7
- import Restore from '../../assets/restore.svg';
8
- import MiniSchedule from '../../assets/mini-schedule.svg';
9
- import DollarCoin from '../../assets/dollar-coin.svg';
10
- import Promotions from '../../assets/promotions.svg';
11
- import Addons from '../../assets/addons.svg';
12
- import ContactSupport from '../../assets/contact-support.svg';
13
-
14
- export const ICON_COMPONENTS: {[name: string]: ((props: SVGProps<SVGElement>) => ReactElement)} = {
15
- RenewSubscription,
16
- BillingInfoCustomer,
17
- CreditCard,
18
- ScheduleBox,
19
- ScheduleClock,
20
- Restore,
21
- MiniSchedule,
22
- DollarCoin,
23
- Promotions,
24
- Addons,
25
- ContactSupport,
26
- };
27
-
28
- export type Icons = keyof typeof ICON_COMPONENTS;
1
+ export { default as Addons } from '../../assets/addons.svg';
2
+ export { default as BillingInfoCustomer } from '../../assets/billing-info-customer.svg';
3
+ export { default as ContactSupport } from '../../assets/contact-support.svg';
4
+ export { default as CreditCard } from '../../assets/credit-card.svg';
5
+ export { default as DollarCoin } from '../../assets/dollar-coin.svg';
6
+ export { default as MiniSchedule } from '../../assets/mini-schedule.svg';
7
+ export { default as Promotions } from '../../assets/promotions.svg';
8
+ export { default as Restore } from '../../assets/restore.svg';
9
+ export { default as ScheduleBox } from '../../assets/schedule-box.svg';
10
+ export { default as ScheduleClock } from '../../assets/schedule.svg';
11
+ export { default as RenewSubscription } from '../../assets/subscription-renews-icon.svg';
12
+ export { default as Trash } from '../../assets/trash.svg';
13
+ export { default as PaymentMethod } from '../../assets/payment-method.svg';
14
+ export { default as OutlinedCircle } from '../../assets/outlined-circle.svg';
15
+ export { default as OutlinedCheckedCircle } from '../../assets/outlined-checked-circle.svg';
16
+ export { default as ArrowForward } from '../../assets/arrow-forward.svg';
17
+ export { default as Close } from '../../assets/close.svg';
@@ -1,8 +1,10 @@
1
1
  import {
2
2
  Alignment,
3
+ CheckoutConfiguration,
3
4
  CustomerPortalConfiguration,
4
5
  FontWeight as JSFontWeight,
5
6
  PaywallConfiguration,
7
+ TypographyConfiguration,
6
8
  } from '@stigg/js-client-sdk';
7
9
  import { CustomizedTheme } from '../../theme/Theme';
8
10
  import { HorizontalAlignment, FontWeight } from '../../theme/types';
@@ -29,10 +31,7 @@ function mapFontWeight(defaultValue: FontWeight, fontWeight?: JSFontWeight | nul
29
31
  }
30
32
  }
31
33
 
32
- function mapTypography(
33
- configuration: CustomerPortalConfiguration | PaywallConfiguration,
34
- ): CustomizedTheme['typography'] {
35
- const { typography } = configuration;
34
+ function mapTypography(typography?: TypographyConfiguration | null): CustomizedTheme['typography'] {
36
35
  return {
37
36
  fontFamilyUrl: typography?.fontFamily || undefined,
38
37
  h1: {
@@ -69,7 +68,7 @@ function mapAlignment(alignment?: Alignment | null): HorizontalAlignment | undef
69
68
  }
70
69
 
71
70
  export function mapCustomerPortalConfiguration(configuration: CustomerPortalConfiguration): CustomizedTheme {
72
- const { palette } = configuration;
71
+ const { palette, typography } = configuration;
73
72
  return {
74
73
  palette: {
75
74
  primary: palette?.primary || undefined,
@@ -80,12 +79,12 @@ export function mapCustomerPortalConfiguration(configuration: CustomerPortalConf
80
79
  primary: palette?.textColor || undefined,
81
80
  },
82
81
  },
83
- typography: mapTypography(configuration),
82
+ typography: mapTypography(typography),
84
83
  };
85
84
  }
86
85
 
87
86
  export function mapPaywallConfiguration(paywallConfiguration: PaywallConfiguration): CustomizedTheme {
88
- const { palette, layout, customCss } = paywallConfiguration;
87
+ const { palette, layout, customCss, typography } = paywallConfiguration;
89
88
  return {
90
89
  customCss: customCss || undefined,
91
90
  palette: {
@@ -97,7 +96,7 @@ export function mapPaywallConfiguration(paywallConfiguration: PaywallConfigurati
97
96
  primary: palette?.textColor || undefined,
98
97
  },
99
98
  },
100
- typography: mapTypography(paywallConfiguration),
99
+ typography: mapTypography(typography),
101
100
  layout: {
102
101
  ctaAlignment: mapAlignment(layout?.alignment),
103
102
  headerAlignment: mapAlignment(layout?.alignment),
@@ -109,3 +108,20 @@ export function mapPaywallConfiguration(paywallConfiguration: PaywallConfigurati
109
108
  },
110
109
  };
111
110
  }
111
+
112
+ export function mapCheckoutConfiguration(configuration: CheckoutConfiguration): CustomizedTheme {
113
+ const { palette, typography } = configuration;
114
+ return {
115
+ palette: {
116
+ primary: palette?.primary || undefined,
117
+ backgroundPaper: palette?.backgroundColor || undefined,
118
+ outlinedBorder: palette?.borderColor || undefined,
119
+ text: {
120
+ primary: palette?.textColor || undefined,
121
+ },
122
+ backgroundHighlight: palette?.selectionColor || undefined,
123
+ backgroundSection: palette?.summaryBackgroundColor || undefined,
124
+ },
125
+ typography: mapTypography(typography),
126
+ };
127
+ }
@@ -10,8 +10,7 @@ import { CustomerPortalSection } from '../../CustomerPortal';
10
10
  import { CustomerPortalLocalization } from '../../customerPortalTextOverrides';
11
11
  import { StyledTabs, TabContent, TabsLayout } from './SubscriptionTabs.style';
12
12
  import { CustomerPortalTheme } from '../../customerPortalTheme';
13
- import { Icon } from '../../../common/Icon';
14
- import { Icons } from '../../../common/customIcons';
13
+ import { Icon, Icons } from '../../../common/Icon';
15
14
  import { FontWeight } from 'styled-typography';
16
15
 
17
16
  type TabPanelProps = {
@@ -41,21 +40,16 @@ export type SubscriptionTabsProps = {
41
40
  function TabTitle({ isSelected, label, icon }: { isSelected: boolean; label: string; icon: Icons }) {
42
41
  const color = isSelected ? 'primary' : 'secondary';
43
42
  return (
44
- <div style={{display: 'flex', gap: 8, alignItems: 'center' }}>
43
+ <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
45
44
  <Icon icon={icon} svgStrokeColor={color} />
46
- <Typography variant="h6" bold={isSelected} fontWeight={FontWeight.Medium} color={color}>
45
+ <Typography variant="h6" bold={isSelected} fontWeight={FontWeight.Medium} color={color}>
47
46
  {label}
48
47
  </Typography>
49
48
  </div>
50
49
  );
51
50
  }
52
51
 
53
- export function SubscriptionTabs({
54
- customerPortal,
55
- hiddenSections,
56
- textOverrides,
57
- theme,
58
- }: SubscriptionTabsProps) {
52
+ export function SubscriptionTabs({ customerPortal, hiddenSections, textOverrides, theme }: SubscriptionTabsProps) {
59
53
  const allAddons = flatMap(customerPortal.subscriptions, subscription => subscription.addons);
60
54
  const isSectionHidden = (sectionName: CustomerPortalSection) =>
61
55
  hiddenSections?.some(section => section === sectionName);
@@ -81,14 +75,14 @@ export function SubscriptionTabs({
81
75
  <Tab
82
76
  sx={{ textTransform: 'none' }}
83
77
  value={1}
84
- label={<TabTitle isSelected={value === 1} label={textOverrides.addonsTabTitle} icon='Addons' />}
78
+ label={<TabTitle isSelected={value === 1} label={textOverrides.addonsTabTitle} icon="Addons" />}
85
79
  />
86
80
  ) : null}
87
81
  {showPromotions ? (
88
82
  <Tab
89
83
  sx={{ textTransform: 'none' }}
90
84
  value={2}
91
- label={<TabTitle isSelected={value === 2} label={textOverrides.promotionsTabTitle} icon='Promotions' />}
85
+ label={<TabTitle isSelected={value === 2} label={textOverrides.promotionsTabTitle} icon="Promotions" />}
92
86
  />
93
87
  ) : null}
94
88
  </StyledTabs>
@@ -0,0 +1,17 @@
1
+ import sortBy from 'lodash/sortBy';
2
+ import { useMemo } from 'react';
3
+
4
+ import { BillingModel, Price } from '@stigg/js-client-sdk';
5
+
6
+ const CHARGES_BILLING_MODEL_ORDER = [BillingModel.FlatFee, BillingModel.PerUnit, BillingModel.UsageBased];
7
+
8
+ export const sortCharges = (charges: Price[]) => {
9
+ return sortBy(charges, [
10
+ charge => CHARGES_BILLING_MODEL_ORDER.indexOf(charge.pricingModel),
11
+ charge => charge.feature?.displayName,
12
+ ]);
13
+ };
14
+
15
+ export const useChargesSort = (charges: Price[]) => {
16
+ return useMemo(() => sortCharges(charges), [charges]);
17
+ };
@@ -11,7 +11,7 @@ import { useStiggContext } from '../..';
11
11
  import { hasPricePointsForPlans } from './utils/hasPricePoints';
12
12
  import { getPlansToDisplay } from './utils/getPlansToDisplay';
13
13
  import { getPlanPrice } from '../utils/getPlanPrice';
14
- import { getSelectedTier } from './planPriceTier';
14
+ import { getSelectedTier } from '../utils/priceTierUtils';
15
15
 
16
16
  const PaywallPlansContainer = styled.div`
17
17
  color: ${({ theme }) => theme.stigg.palette.text.primary};
@@ -11,7 +11,7 @@ import classNames from 'classnames';
11
11
  import { Grid } from '@mui/material';
12
12
  import MiniSchedule from '../../assets/mini-schedule.svg';
13
13
  import { PlanPrice } from './PlanPrice';
14
- import { getSelectedTier } from './planPriceTier';
14
+ import { getSelectedTier } from '../utils/priceTierUtils';
15
15
 
16
16
  const PlanOfferingContainer = styled.div<{ $isHighlighted: boolean; $isCurrentPlan: boolean }>`
17
17
  position: relative;
@@ -9,7 +9,7 @@ import ClipLoader from 'react-spinners/ClipLoader';
9
9
  import { Typography } from '../common/Typography';
10
10
  import { getSubscriptionScheduleUpdateTexts } from '../utils/getSubscriptionScheduleUpdateTexts';
11
11
  import { isFunction } from 'lodash';
12
- import { compareSelectedTierToCurrentTier, PriceTierComparison } from './planPriceTier';
12
+ import { compareSelectedTierToCurrentTier, PriceTierComparison } from '../utils/priceTierUtils';
13
13
 
14
14
  const LoadingIndicator = styled(ClipLoader)`
15
15
  margin-left: 10px;
@@ -5,7 +5,7 @@ import { Typography } from '../common/Typography';
5
5
  import React, { useEffect, useState } from 'react';
6
6
  import styled from '@emotion/styled/macro';
7
7
  import { BillingPeriod, PriceTierFragment } from '@stigg/js-client-sdk';
8
- import { TiersLayout } from './TiersLayout';
8
+ import { TiersSelectContainer } from '../common/TiersSelectContainer';
9
9
 
10
10
  const EMPTY_CHAR = '‎';
11
11
 
@@ -138,8 +138,8 @@ export const PlanPrice = ({
138
138
  )}
139
139
 
140
140
  {withTiersRow && (
141
- <TiersLayout
142
- plan={plan}
141
+ <TiersSelectContainer
142
+ componentId={`${plan.id}_${featureId}_tier`}
143
143
  tiers={tiers}
144
144
  tierUnits={tierUnits}
145
145
  selectedTier={selectedTier}
@@ -3,16 +3,21 @@ export function calculateUnitQuantityText(
3
3
  maxUnitQuantity?: number | null,
4
4
  unitsPlural?: string | null,
5
5
  ) {
6
+ const unitsText = unitsPlural ? ` ${unitsPlural}` : '';
7
+
6
8
  // copy for only maxunit
7
9
  if ((!minUnitQuantity || minUnitQuantity === 1) && maxUnitQuantity) {
8
- return `Up to ${maxUnitQuantity} ${unitsPlural}`;
10
+ return `Up to ${maxUnitQuantity}${unitsText}`;
9
11
  }
12
+
10
13
  // both limits
11
14
  if (minUnitQuantity && minUnitQuantity > 1 && maxUnitQuantity) {
12
- return `${minUnitQuantity}-${maxUnitQuantity} ${unitsPlural}`;
15
+ return `${minUnitQuantity}-${maxUnitQuantity}${unitsText}`;
13
16
  }
17
+
14
18
  if (minUnitQuantity && minUnitQuantity > 1) {
15
- return `Minimum ${minUnitQuantity} ${unitsPlural}`;
19
+ return `Minimum ${minUnitQuantity}${unitsText}`;
16
20
  }
21
+
17
22
  return '';
18
- }
23
+ }
@@ -2,7 +2,7 @@ import { BillingPeriod, PaywallCalculatedPricePoint, Price } from '@stigg/js-cli
2
2
  import isNil from 'lodash/isNil';
3
3
  import { PaywallPlan } from '../paywall';
4
4
 
5
- function calculateDiscountRate(monthlyPrice?: number | null, annuallyPrice?: number | null) {
5
+ export function calculateDiscountRate(monthlyPrice?: number | null, annuallyPrice?: number | null) {
6
6
  if (!isNil(monthlyPrice) && !isNil(annuallyPrice)) {
7
7
  const annuallyPerMonthPrice = annuallyPrice / 12;
8
8
  return Math.round(((monthlyPrice - annuallyPerMonthPrice) / monthlyPrice) * 100);
@@ -8,7 +8,7 @@ export const currencyPriceFormatter = ({
8
8
  maximumFractionDigits = 5,
9
9
  }: {
10
10
  amount: number;
11
- currency?: Currency;
11
+ currency?: Currency | string;
12
12
  locale?: string;
13
13
  maximumFractionDigits?: number;
14
14
  }) => {
@@ -7,7 +7,7 @@ import {
7
7
  } from '@stigg/js-client-sdk';
8
8
  import { currencyPriceFormatter } from './currencyUtils';
9
9
  import { PlanPriceText } from './getPlanPrice';
10
- import { calculateTierPrice } from '../paywall/planPriceTier';
10
+ import { calculateTierPrice, getPriceFeatureUnit } from './priceTierUtils';
11
11
 
12
12
  type GetPaidPriceTextParams = {
13
13
  planPrices: Price[];
@@ -44,7 +44,7 @@ export function getPaidPriceText({
44
44
  currentTier = selectedTierByFeature[price.feature!.featureId] || currentTier;
45
45
 
46
46
  tiers = price.tiers;
47
- tierUnits = price.feature!.unitsPlural || '';
47
+ tierUnits = getPriceFeatureUnit(price);
48
48
  }
49
49
 
50
50
  priceNumber += calculateTierPrice(price, currentTier, selectedBillingPeriod, shouldShowMonthlyPriceAmount);
@@ -1,7 +1,30 @@
1
- import { PaywallPlan } from './types';
1
+ import { PaywallPlan } from '../paywall/types';
2
2
 
3
3
  import { BillingModel, TiersMode, BillingPeriod, Price, PriceTierFragment, Subscription } from '@stigg/js-client-sdk';
4
4
 
5
+ export function getPriceFeatureUnit(price: Price) {
6
+ if (!price.feature) {
7
+ return '';
8
+ }
9
+
10
+ return (price.feature!.unitQuantity != 1 ? price.feature!.unitsPlural : price.feature!.units) || '';
11
+ }
12
+
13
+ export function getTierByQuantity(tiers: PriceTierFragment[], quantity: number) {
14
+ if (!tiers) return;
15
+
16
+ const ascendingTiers = [...tiers];
17
+ ascendingTiers.sort((a, b) => a.upTo - b.upTo);
18
+
19
+ for (const tier of ascendingTiers) {
20
+ if (quantity <= tier.upTo) {
21
+ return tier;
22
+ }
23
+ }
24
+
25
+ return ascendingTiers[ascendingTiers.length - 1];
26
+ }
27
+
5
28
  export function calculateTierPrice(
6
29
  price: Price,
7
30
  currentTier: PriceTierFragment,
@@ -46,8 +69,7 @@ export function getSelectedTier(
46
69
  );
47
70
 
48
71
  if (tieredPrice) {
49
- const customerTier = price.tiers!.find(tier => tier.upTo === tieredPrice.feature!.unitQuantity);
50
- currentTier = customerTier || price.tiers![0];
72
+ currentTier = getTierByQuantity(price.tiers!, tieredPrice.feature!.unitQuantity || 1)!;
51
73
  }
52
74
  }
53
75
 
@@ -0,0 +1,10 @@
1
+ import { Price } from '@stigg/js-client-sdk';
2
+
3
+ export const getValidPriceQuantity = (price: Price, quantity: number) => {
4
+ if (price.minUnitQuantity && quantity < price.minUnitQuantity) {
5
+ return price.minUnitQuantity;
6
+ } else if (price.maxUnitQuantity && quantity > price.maxUnitQuantity) {
7
+ return price.maxUnitQuantity;
8
+ }
9
+ return quantity;
10
+ };
package/src/index.ts CHANGED
@@ -29,6 +29,7 @@ export {
29
29
  StiggContextValue,
30
30
  StiggContext,
31
31
  } from './components/StiggProvider';
32
+ export { Checkout, CheckoutProps, CheckoutTheme } from './components/checkout';
32
33
  export { useWaitForCheckoutCompleted, ProvisionStatus } from './components/hooks';
33
34
  export { HorizontalAlignment, TextAlignment } from './theme/types';
34
35
  export { CustomizedTheme as Theme } from './theme/Theme';
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+ import styled from '@emotion/styled/macro';
3
+ import { ComponentMeta, ComponentStory } from '@storybook/react';
4
+ import { Checkout } from '../components/checkout';
5
+ import { StiggProvider } from '../components/StiggProvider';
6
+ import { defaultArgsWithCustomer } from './baseArgs';
7
+
8
+ export default {
9
+ title: 'Stigg React SDK/Checkout',
10
+ component: Checkout,
11
+ decorators: [
12
+ (Story, { args }) => (
13
+ <StiggProvider
14
+ apiKey={args.apiKey}
15
+ customerId={args.customerId}
16
+ theme={args.theme}
17
+ locale={args.locale}
18
+ baseUri={args.baseUri}
19
+ enableEdge={args.disableEdge}
20
+ >
21
+ <Story />
22
+ </StiggProvider>
23
+ ),
24
+ ],
25
+ } as ComponentMeta<typeof Checkout>;
26
+
27
+ const Wrapper = styled.div`
28
+ width: 1000px;
29
+ `;
30
+
31
+ const Template: ComponentStory<any> = args => (
32
+ <Wrapper>
33
+ <Checkout
34
+ planId={args.planId}
35
+ preferredBillingPeriod={args.preferredBillingPeriod}
36
+ billingCountryCode={args.billingCountryCode}
37
+ resourceId={args.resourceId}
38
+ onCheckoutCompleted={results => {
39
+ console.log('checkout finished!', results);
40
+ return Promise.resolve();
41
+ }}
42
+ onCheckout={async ({ checkoutParams, checkoutAction }) => {
43
+ console.log('checkout started!', checkoutParams);
44
+ const { success, errorMessage } = await checkoutAction();
45
+ return { success, errorMessage };
46
+ }}
47
+ onChangePlan={({ currentPlan }) => {
48
+ console.log('plan changed clicked!', { currentPlan });
49
+ }}
50
+ />
51
+ </Wrapper>
52
+ );
53
+
54
+ export const DefaultCheckout = Template.bind({});
55
+ DefaultCheckout.args = {
56
+ ...defaultArgsWithCustomer,
57
+ planId: 'plan-revvenu-essentials',
58
+ baseUri: 'http://localhost:4000',
59
+ apiKey: 'client-72b058a6-0f22-4c86-adce-bf266d12e12e:9f356ceb-c94c-42a4-9572-10b12824da81',
60
+ // baseUri: 'https://api-staging.stigg.io',
61
+ // apiKey: 'client-79584f52-7ef9-4c58-b9ac-5080acf492e4:71f2274c-100a-4fa4-8a43-48fa3b16c627',
62
+ };
@@ -39,7 +39,7 @@ export default {
39
39
  </StiggProvider>
40
40
  ),
41
41
  ],
42
- } as ComponentMeta<typeof Paywall>;
42
+ } as ComponentMeta<typeof CustomerPortal>;
43
43
 
44
44
  const Wrapper = styled.div`
45
45
  width: 1000px;
@@ -1,16 +1,17 @@
1
+ import { merge } from 'lodash';
1
2
  import React, { PropsWithChildren } from 'react';
3
+ import { ThemeProvider as StyledThemeProvider } from 'styled-components';
2
4
  import { TypographyProps } from 'styled-typography';
3
- import { css } from '@emotion/react';
5
+
6
+ import { css, ThemeProvider } from '@emotion/react';
4
7
  import styled from '@emotion/styled/macro';
5
- import { ThemeProvider } from '@emotion/react';
6
- import { ThemeProvider as MuiThemeProvider, createTheme } from '@mui/material/styles';
7
- import { ThemeProvider as StyledThemeProvider } from 'styled-components';
8
- import { Fonts } from './Fonts';
9
- import { DeepPartial } from '../types';
10
- import { StiggTheme } from './types';
8
+ import { createTheme, ThemeProvider as MuiThemeProvider } from '@mui/material/styles';
9
+
11
10
  import { useStiggContext } from '../components/StiggProvider';
12
- import { merge } from 'lodash';
11
+ import { DeepPartial } from '../types';
12
+ import { Fonts } from './Fonts';
13
13
  import { getResolvedTheme } from './getResolvedTheme';
14
+ import { StiggTheme } from './types';
14
15
 
15
16
  export type CustomizedTheme = DeepPartial<StiggTheme>;
16
17
 
@@ -18,6 +18,7 @@ export const getResolvedTheme = (customizedTheme?: CustomizedTheme): StiggTheme
18
18
  const baseTheme: StiggTheme = {
19
19
  palette: {
20
20
  primary: primaryColor.hex(),
21
+ primaryDark: primaryColor.darken(0.3).hex(),
21
22
  backgroundPaper: '#FFFFFF',
22
23
  backgroundHighlight: '#F5F6F9',
23
24
  backgroundSection: primaryColor.alpha(0.1).toString(),
@@ -8,6 +8,7 @@ export type FontVariant = {
8
8
  export type StiggTheme = {
9
9
  palette: {
10
10
  primary: string;
11
+ primaryDark: string;
11
12
  backgroundPaper: string;
12
13
  backgroundHighlight: string;
13
14
  backgroundSection: string;