@stigg/react-sdk 4.12.0 → 4.13.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.
Files changed (28) hide show
  1. package/dist/components/common/Typography.d.ts +2 -0
  2. package/dist/components/paywall/Paywall.d.ts +3 -2
  3. package/dist/components/paywall/PaywallContainer.d.ts +3 -2
  4. package/dist/components/paywall/PlanOffering.d.ts +3 -2
  5. package/dist/components/paywall/types.d.ts +3 -0
  6. package/dist/components/utils/priceTierUtils.d.ts +3 -2
  7. package/dist/react-sdk.cjs.development.js +69 -36
  8. package/dist/react-sdk.cjs.development.js.map +1 -1
  9. package/dist/react-sdk.cjs.production.min.js +1 -1
  10. package/dist/react-sdk.cjs.production.min.js.map +1 -1
  11. package/dist/react-sdk.esm.js +76 -37
  12. package/dist/react-sdk.esm.js.map +1 -1
  13. package/package.json +1 -1
  14. package/src/components/common/TiersSelectContainer.tsx +1 -1
  15. package/src/components/common/Typography.tsx +3 -0
  16. package/src/components/customerPortal/billing/PaymentDetailsSection.tsx +8 -4
  17. package/src/components/customerPortal/subscriptionOverview/tabs/Promotions.tsx +3 -3
  18. package/src/components/customerPortal/subscriptionOverview/tabs/SubscriptionTabs.style.tsx +1 -1
  19. package/src/components/customerPortal/subscriptionOverview/upcomingBilling/NextEstimatedBill.tsx +1 -1
  20. package/src/components/customerPortal/usage/CustomerUsageData.tsx +1 -1
  21. package/src/components/customerPortal/usage/featureUsage/FeatureUsageProgressBar.tsx +3 -1
  22. package/src/components/paywall/Paywall.tsx +10 -1
  23. package/src/components/paywall/PaywallContainer.tsx +4 -1
  24. package/src/components/paywall/PlanOffering.tsx +4 -2
  25. package/src/components/paywall/PlanPrice.tsx +6 -4
  26. package/src/components/paywall/types.ts +2 -0
  27. package/src/components/utils/priceTierUtils.ts +5 -3
  28. package/src/stories/Checkout.stories.tsx +1 -1
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.12.0",
2
+ "version": "4.13.0",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -48,7 +48,7 @@ export function TiersSelectContainer({
48
48
  };
49
49
 
50
50
  return (
51
- <Typography className="stigg-price-tier-select" style={{ minHeight: '46px' }}>
51
+ <Typography as="div" className="stigg-price-tier-select" style={{ minHeight: '46px' }}>
52
52
  {tiers ? (
53
53
  <TierSelect
54
54
  value={selectedTier ? selectedTier.upTo.toString() : tiers[0].upTo.toString()}
@@ -25,6 +25,7 @@ export type TypographyProps = {
25
25
  className?: string;
26
26
  bold?: boolean;
27
27
  span?: boolean;
28
+ as?: 'div' | 'p' | 'span';
28
29
  } & Omit<TypeProps, 'color' | 'level'>;
29
30
 
30
31
  function getColor(theme: Theme, $color: Colors) {
@@ -105,6 +106,7 @@ export const Typography = forwardRef((props: TypographyProps, ref) => {
105
106
  color = 'primary',
106
107
  overrideColor,
107
108
  bold,
109
+ as = 'p',
108
110
  ...rest
109
111
  } = props;
110
112
  const theme = useTheme();
@@ -114,6 +116,7 @@ export const Typography = forwardRef((props: TypographyProps, ref) => {
114
116
 
115
117
  return (
116
118
  <StyledText
119
+ as={as}
117
120
  ref={ref}
118
121
  {...rest}
119
122
  className={className}
@@ -22,13 +22,13 @@ export function PaymentDetailsSection() {
22
22
  if (isLoadingData) {
23
23
  items.push(
24
24
  ...[
25
- <InformationGridContainer>
25
+ <InformationGridContainer key="information-loading-data-top">
26
26
  <Skeleton width={220} height={12} />
27
27
  <Skeleton width={220} height={12} />
28
28
  <Skeleton width={220} height={12} />
29
29
  </InformationGridContainer>,
30
- <Divider orientation="vertical" style={{ minHeight: 93 }} />,
31
- <InformationGridContainer>
30
+ <Divider key="information-loading-data-divider" orientation="vertical" style={{ minHeight: 93 }} />,
31
+ <InformationGridContainer key="information-loading-data-bottom">
32
32
  <Skeleton width={220} height={12} />
33
33
  <Skeleton width={220} height={12} />
34
34
  <Skeleton width={220} height={12} />
@@ -38,6 +38,7 @@ export function PaymentDetailsSection() {
38
38
  } else {
39
39
  items.push(
40
40
  <InformationGrid
41
+ key="information-billing-data-billed-to"
41
42
  title="Billed to"
42
43
  rows={[
43
44
  {
@@ -62,9 +63,12 @@ export function PaymentDetailsSection() {
62
63
  billingInformation.defaultPaymentExpirationMonth &&
63
64
  billingInformation.defaultPaymentExpirationYear
64
65
  ) {
65
- items.unshift(<Divider orientation="vertical" style={{ minHeight: 93 }} />);
66
+ items.unshift(
67
+ <Divider key="information-billing-data-divider" orientation="vertical" style={{ minHeight: 93 }} />,
68
+ );
66
69
  items.unshift(
67
70
  <InformationGrid
71
+ key="information-billing-data-payment-method"
68
72
  title="Payment method"
69
73
  rows={[
70
74
  {
@@ -13,7 +13,7 @@ const Row = styled.div<{ $borderColor: string }>`
13
13
  border-bottom: ${({ $borderColor }) => `1px solid ${$borderColor}`};
14
14
  padding: 16px 0;
15
15
 
16
- & > *:first-child {
16
+ & > *:first-of-type {
17
17
  max-width: 60%;
18
18
  }
19
19
  `;
@@ -47,8 +47,8 @@ export function Promotions() {
47
47
  Expiration date
48
48
  </Typography>
49
49
  </Row>
50
- {promotionalEntitlements?.map((promotionalEntitlement) => (
51
- <Row $borderColor={theme.borderColor}>
50
+ {promotionalEntitlements?.map((promotionalEntitlement, index) => (
51
+ <Row key={`${promotionalEntitlement.displayName}-${index}`} $borderColor={theme.borderColor}>
52
52
  <Typography variant="body1">{getPromotionTitle(promotionalEntitlement)}</Typography>
53
53
  <Typography variant="body1" color="disabled">
54
54
  {promotionalEntitlement.endDate
@@ -14,7 +14,7 @@ export const TabsLayout = styled.div`
14
14
  margin-top: 16px;
15
15
  `;
16
16
 
17
- export const TabContent = styled(Box)<{ $maxHeight: string }>`
17
+ export const TabContent = styled(Box, { shouldForwardProp: (prop) => !prop.startsWith('$') })<{ $maxHeight: string }>`
18
18
  margin-top: 16px;
19
19
  max-height: ${({ $maxHeight }) => $maxHeight};
20
20
  overflow-y: auto;
@@ -16,7 +16,7 @@ export function NextEstimatedBill({ billingPeriod, rangeEnd, amount, currency }:
16
16
  <>
17
17
  <Typography variant="h6">Next estimated bill</Typography>
18
18
  <Typography variant="h1">{currencyPriceFormatter({ amount, currency, maximumFractionDigits: 2 })}</Typography>
19
- <Typography variant="body1" color="secondary">
19
+ <Typography as="div" variant="body1" color="secondary">
20
20
  Billed {billingPeriod === BillingPeriod.Monthly ? 'monthly' : 'annually'} on{' '}
21
21
  <Typography variant="body1" span color="primary">
22
22
  {moment.utc(rangeEnd).format('MMM Do, YYYY')}
@@ -77,7 +77,7 @@ export function CustomerUsageData({ onManageSubscription, onBuyMore }: CustomerU
77
77
  <>
78
78
  <Grid container spacing={4}>
79
79
  {entitlementsToShow.map((entitlement) => (
80
- <Grid item xs={xs}>
80
+ <Grid key={entitlement.feature!.refId} item xs={xs}>
81
81
  <FeatureUsage
82
82
  key={entitlement.feature!.refId}
83
83
  subscriptionPrice={subscriptionPriceByFeature[entitlement.feature!.refId]}
@@ -6,7 +6,9 @@ import Divider from '@mui/material/Divider';
6
6
  import Color from 'color';
7
7
  import { getUsagePercentage, getUsageProgressStatus } from './FeatureUsage.helper';
8
8
 
9
- export const StyledLinearProgress = styled(LinearProgress)<{ $progressStatus: 'standard' | 'warning' | 'error' }>`
9
+ export const StyledLinearProgress = styled(LinearProgress, { shouldForwardProp: (prop) => !prop.startsWith('$') })<{
10
+ $progressStatus: 'standard' | 'warning' | 'error';
11
+ }>`
10
12
  height: 4px;
11
13
  background-color: ${({ theme }) => Color(theme.stigg.palette.primary).alpha(0.4).string()};
12
14
 
@@ -4,7 +4,13 @@ import styled from '@emotion/styled/macro';
4
4
  import { PlanOffering } from './PlanOffering';
5
5
  import { BillingPeriodPicker } from './BillingPeriodPicker';
6
6
  import { calculatePaywallDiscountRate } from '../utils/calculateDiscountRate';
7
- import { ShouldHidePlanFn, OnPlanSelectedCallbackFn, PaywallPlan, SubscribeIntentionType } from './types';
7
+ import {
8
+ ShouldHidePlanFn,
9
+ OnPlanSelectedCallbackFn,
10
+ PaywallPlan,
11
+ SubscribeIntentionType,
12
+ SelectDefaultTierIndexFn,
13
+ } from './types';
8
14
  import { PaywallLocalization } from './paywallTextOverrides';
9
15
  import { PoweredByStigg } from '../common/PoweredByStigg';
10
16
  import { useStiggContext } from '../..';
@@ -52,6 +58,7 @@ type PaywallProps = {
52
58
  paywallLocale: PaywallLocalization;
53
59
  locale: string;
54
60
  shouldHidePlan?: ShouldHidePlanFn;
61
+ selectDefaultTierIndex?: SelectDefaultTierIndexFn;
55
62
  };
56
63
 
57
64
  export const Paywall = ({
@@ -67,6 +74,7 @@ export const Paywall = ({
67
74
  paywallLocale,
68
75
  locale,
69
76
  shouldHidePlan,
77
+ selectDefaultTierIndex,
70
78
  }: PaywallProps) => {
71
79
  const { stigg } = useStiggContext();
72
80
  const discountRate = calculatePaywallDiscountRate(plans);
@@ -158,6 +166,7 @@ export const Paywall = ({
158
166
  locale={locale}
159
167
  customer={customer}
160
168
  isCustomerInCustomPlan={isCustomerInCustomPlan}
169
+ selectDefaultTierIndex={selectDefaultTierIndex}
161
170
  />
162
171
  ))}
163
172
  </PaywallPlansContainer>
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { BillingPeriod } from '@stigg/js-client-sdk';
3
3
  import { Paywall } from './Paywall';
4
4
  import { useLoadPaywallData } from './hooks/useLoadPaywallData';
5
- import { ShouldHidePlanFn, OnPlanSelectedCallbackFn } from './types';
5
+ import { ShouldHidePlanFn, OnPlanSelectedCallbackFn, SelectDefaultTierIndexFn } from './types';
6
6
  import { getResolvedPaywallLocalize, PaywallLocalization } from './paywallTextOverrides';
7
7
  import { DeepPartial } from '../../types';
8
8
  import { PaywallLoader } from './PaywallLoader';
@@ -24,6 +24,7 @@ export type PaywallContainerProps = {
24
24
  textOverrides?: DeepPartial<PaywallLocalization>;
25
25
  billingCountryCode?: string;
26
26
  shouldHidePlan?: ShouldHidePlanFn;
27
+ selectDefaultTierIndex?: SelectDefaultTierIndexFn;
27
28
  };
28
29
 
29
30
  export const PaywallContainer = ({
@@ -37,6 +38,7 @@ export const PaywallContainer = ({
37
38
  onBillingPeriodChange,
38
39
  billingCountryCode,
39
40
  shouldHidePlan,
41
+ selectDefaultTierIndex,
40
42
  }: PaywallContainerProps) => {
41
43
  const hasCustomerPortalContext = useCheckContextExists(CustomerPortalContext);
42
44
  let isCustomerPortalLoading = false;
@@ -89,6 +91,7 @@ export const PaywallContainer = ({
89
91
  paywallLocale={paywallLocale}
90
92
  locale={locale}
91
93
  shouldHidePlan={shouldHidePlan}
94
+ selectDefaultTierIndex={selectDefaultTierIndex}
92
95
  />
93
96
  );
94
97
 
@@ -12,7 +12,7 @@ import classNames from 'classnames';
12
12
  import Grid from '@mui/material/Grid';
13
13
  import { PlanEntitlements } from './PlanEntitlements';
14
14
  import { PlanOfferingButton } from './PlanOfferingButton';
15
- import { PaywallPlan, SubscribeIntentionType } from './types';
15
+ import { PaywallPlan, SelectDefaultTierIndexFn, SubscribeIntentionType } from './types';
16
16
  import { PaywallLocalization } from './paywallTextOverrides';
17
17
  import { flexLayoutMapper } from '../../theme/getResolvedTheme';
18
18
  import { Typography } from '../common/Typography';
@@ -92,6 +92,7 @@ type PlanOfferingProps = {
92
92
  locale: string;
93
93
  withStartingAtRow: boolean;
94
94
  isCustomerInCustomPlan: boolean;
95
+ selectDefaultTierIndex?: SelectDefaultTierIndexFn;
95
96
  };
96
97
 
97
98
  const NextPlanTagContainer = styled.div`
@@ -143,6 +144,7 @@ export function PlanOffering({
143
144
  locale,
144
145
  withStartingAtRow,
145
146
  isCustomerInCustomPlan,
147
+ selectDefaultTierIndex,
146
148
  }: PlanOfferingProps) {
147
149
  const isNextPlan = plan.isNextPlan && plan.isNextPlan(billingPeriod);
148
150
  const planPrices = plan.pricePoints.filter((pricePoint) => pricePoint.billingPeriod === billingPeriod);
@@ -166,7 +168,7 @@ export function PlanOffering({
166
168
  }
167
169
 
168
170
  const [selectedTierByFeature, setSelectedTierByFeature] = React.useState<Record<string, PriceTierFragment>>(
169
- getSelectedTier(plan, billingPeriod, currentSubscription, {}),
171
+ getSelectedTier(plan, billingPeriod, currentSubscription, {}, selectDefaultTierIndex),
170
172
  );
171
173
 
172
174
  useEffect(() => {
@@ -107,7 +107,7 @@ export const PlanPrice = ({
107
107
  };
108
108
 
109
109
  return (
110
- <PlanPriceContainer className="stigg-price-text">
110
+ <PlanPriceContainer as="div" className="stigg-price-text">
111
111
  <>
112
112
  {withStartingAtRow && (
113
113
  <Typography
@@ -119,11 +119,13 @@ export const PlanPrice = ({
119
119
  </Typography>
120
120
  )}
121
121
 
122
- <PriceSpan variant="h1">{price}</PriceSpan>
122
+ <PriceSpan className="stigg-price-point" variant="h1">
123
+ {price}
124
+ </PriceSpan>
123
125
 
124
126
  {withUnitPriceRow && (
125
- <Typography className="stigg-price-unit-and-billing-period-text" style={{ minHeight: '48px' }}>
126
- <UnitSpan span variant="h6" color="secondary">
127
+ <Typography as="div" className="stigg-price-unit-and-billing-period-text" style={{ minHeight: '48px' }}>
128
+ <UnitSpan className="stigg-price-unit-text" span variant="h6" color="secondary">
127
129
  {unit}
128
130
  </UnitSpan>
129
131
 
@@ -63,3 +63,5 @@ export type OnPlanSelectedCallbackFn = ({
63
63
  }) => void | Promise<void>;
64
64
 
65
65
  export type ShouldHidePlanFn = ({ plan }: { plan: PaywallPlan }) => boolean | Promise<boolean>;
66
+
67
+ export type SelectDefaultTierIndexFn = ({ plan }: { plan: PaywallPlan }) => number;
@@ -1,5 +1,6 @@
1
1
  import { BillingModel, TiersMode, BillingPeriod, Price, PriceTierFragment, Subscription } from '@stigg/js-client-sdk';
2
- import { PaywallPlan } from '../paywall/types';
2
+ import { PaywallPlan } from '../paywall';
3
+ import { SelectDefaultTierIndexFn } from '../paywall/types';
3
4
 
4
5
  export function getPriceFeatureUnit(price: Price) {
5
6
  if (!price.feature) {
@@ -49,6 +50,7 @@ export function getSelectedTier(
49
50
  billingPeriod: BillingPeriod,
50
51
  currentSubscription: Subscription | null,
51
52
  selectedTierByFeature: Record<string, PriceTierFragment>,
53
+ selectDefaultTierIndex?: SelectDefaultTierIndexFn,
52
54
  ): Record<string, PriceTierFragment> {
53
55
  const planTierPrices = plan.pricePoints.filter(
54
56
  (price) => price.billingPeriod === billingPeriod && price.isTieredPrice,
@@ -57,8 +59,8 @@ export function getSelectedTier(
57
59
  if (planTierPrices.length === 1) {
58
60
  const [price] = planTierPrices;
59
61
  const { featureId } = price.feature!;
60
-
61
- let currentTier = price.tiers![0];
62
+ const selectedDefaultTierIndex = selectDefaultTierIndex ? selectDefaultTierIndex({ plan }) : 0;
63
+ let currentTier = price.tiers![selectedDefaultTierIndex];
62
64
 
63
65
  if (selectedTierByFeature[featureId]) {
64
66
  currentTier = price.tiers?.find((tier) => tier.upTo === selectedTierByFeature[featureId].upTo) || currentTier;
@@ -18,7 +18,7 @@ export default {
18
18
  theme={args.theme}
19
19
  locale={args.locale}
20
20
  baseUri={args.baseUri}
21
- enableEdge={args.disableEdge}>
21
+ enableEdge={!args.disableEdge}>
22
22
  <Story />
23
23
  </StiggProvider>
24
24
  ),