@codecademy/brand 3.6.0-alpha.eb8166002f.0 → 3.6.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/AppHeader/AppHeaderElements/AppHeaderCatalogDropdown/NavPanels.js +31 -103
- package/dist/AppHeaderMobile/AppHeaderMainMenuMobile/index.js +1 -1
- package/dist/GlobalHeader/GlobalHeaderVariants.js +1 -1
- package/dist/LearningOutcomeFlyout/index.js +52 -11
- package/dist/LearningOutcomeFlyout/types.d.ts +2 -0
- package/dist/PricingSection/ConditionalColorMode.d.ts +4 -0
- package/dist/PricingSection/ConditionalColorMode.js +13 -0
- package/dist/PricingSection/PricingCard/PricingAmount.d.ts +7 -3
- package/dist/PricingSection/PricingCard/PricingAmount.js +92 -61
- package/dist/PricingSection/PricingCard/consts.js +14 -0
- package/dist/PricingSection/PricingCard/index.d.ts +6 -6
- package/dist/PricingSection/PricingCard/index.js +112 -153
- package/dist/PricingSection/PricingCard/types.d.ts +40 -0
- package/dist/PricingSection/PricingCard/types.js +63 -0
- package/dist/PricingSection/ProductCTA.d.ts +7 -5
- package/dist/PricingSection/ProductCTA.js +96 -31
- package/dist/PricingSection/Products.d.ts +4 -4
- package/dist/PricingSection/Products.js +28 -13
- package/dist/PricingSection/config.d.ts +1 -1
- package/dist/PricingSection/config.js +4 -2
- package/dist/PricingSection/index.d.ts +4 -5
- package/dist/PricingSection/index.js +27 -46
- package/dist/PricingSection/types.d.ts +3 -2
- package/dist/PricingSection/types.js +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const
|
|
1
|
+
import { Product, ProductDetails, User } from './types';
|
|
2
|
+
export declare const getCTATitle: (product: Product, isTrialPlan: boolean, isPlusUser?: boolean) => "" | "Request a demo" | "Try Teams for free" | "Purchase now" | "Sign up" | "Try Pro for free" | "Upgrade to Pro" | "Upgrade now" | "Try Plus for free" | "Your current plan";
|
|
3
|
+
export declare const ProductCTA: ({ product, productDetails, user, simple, }: {
|
|
3
4
|
product: Product;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
productDetails: ProductDetails;
|
|
6
|
+
user: User;
|
|
7
|
+
simple?: boolean;
|
|
8
|
+
}) => import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1,44 +1,109 @@
|
|
|
1
|
-
import { FillButton, StrokeButton } from '@codecademy/gamut';
|
|
1
|
+
import { Box, FillButton, FlexBox, StrokeButton, Text } from '@codecademy/gamut';
|
|
2
2
|
import { Product } from './types';
|
|
3
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
-
const
|
|
3
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
export const getCTATitle = (product, isTrialPlan, isPlusUser) => {
|
|
5
5
|
switch (product) {
|
|
6
|
+
case Product.Teams:
|
|
7
|
+
if (isTrialPlan) {
|
|
8
|
+
return 'Try Teams for free';
|
|
9
|
+
}
|
|
10
|
+
return 'Purchase now';
|
|
11
|
+
case Product.Enterprise:
|
|
12
|
+
return 'Request a demo';
|
|
6
13
|
case Product.Basic:
|
|
7
|
-
return
|
|
8
|
-
|
|
9
|
-
href: '/register'
|
|
10
|
-
};
|
|
11
|
-
case Product.Silver:
|
|
12
|
-
return {
|
|
13
|
-
label: 'Try Plus for free',
|
|
14
|
-
href: '/checkout?plan_id=proSilverAnnualV2_7trial&plan_type=plus'
|
|
15
|
-
};
|
|
14
|
+
return 'Sign up';
|
|
15
|
+
case Product.Pro:
|
|
16
16
|
case Product.Gold:
|
|
17
|
+
if (isTrialPlan) {
|
|
18
|
+
return 'Try Pro for free';
|
|
19
|
+
}
|
|
20
|
+
if (isPlusUser) return 'Upgrade to Pro';
|
|
21
|
+
return 'Upgrade now';
|
|
22
|
+
case Product.Silver:
|
|
23
|
+
if (isTrialPlan) {
|
|
24
|
+
return 'Try Plus for free';
|
|
25
|
+
}
|
|
26
|
+
if (isPlusUser) return 'Your current plan';
|
|
27
|
+
return 'Upgrade now';
|
|
28
|
+
default:
|
|
29
|
+
return '';
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const getCTAUrl = ({
|
|
33
|
+
product,
|
|
34
|
+
productDetails,
|
|
35
|
+
userHasSilver
|
|
36
|
+
}) => {
|
|
37
|
+
const planId = productDetails?.planId;
|
|
38
|
+
switch (product) {
|
|
39
|
+
case Product.Basic:
|
|
40
|
+
return '/register';
|
|
17
41
|
case Product.Pro:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
42
|
+
case Product.Silver:
|
|
43
|
+
case Product.Gold:
|
|
44
|
+
if (userHasSilver) {
|
|
45
|
+
return '/account/billing?changePlan=true';
|
|
46
|
+
}
|
|
47
|
+
return `/checkout?plan_id=${planId || undefined}`;
|
|
48
|
+
case Product.Teams:
|
|
49
|
+
return '/business/checkout?plan_type=trial';
|
|
50
|
+
case Product.Enterprise:
|
|
51
|
+
return '/business/teams-quote';
|
|
22
52
|
default:
|
|
23
|
-
return
|
|
24
|
-
label: 'Try Pro for free',
|
|
25
|
-
href: '/checkout'
|
|
26
|
-
};
|
|
53
|
+
return '';
|
|
27
54
|
}
|
|
28
55
|
};
|
|
29
56
|
export const ProductCTA = ({
|
|
30
57
|
product,
|
|
31
|
-
|
|
32
|
-
|
|
58
|
+
productDetails,
|
|
59
|
+
user,
|
|
60
|
+
simple
|
|
33
61
|
}) => {
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
62
|
+
const userHasBasic = !user.anonymous && (!user.proSilver || !user.proGold);
|
|
63
|
+
const userHasSilver = user.proSilver;
|
|
64
|
+
const isTeams = product === Product.Teams;
|
|
65
|
+
const shouldHideCTA = () => {
|
|
66
|
+
if (isTeams) return false;
|
|
67
|
+
if ((userHasBasic || userHasSilver) && product === Product.Basic) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
if (userHasSilver) return false;
|
|
71
|
+
if (user.proGold) return true;
|
|
72
|
+
return false;
|
|
73
|
+
};
|
|
74
|
+
const hideCTAButton = shouldHideCTA();
|
|
75
|
+
const ButtonComponent = product === Product.Gold || product === Product.Pro || product === Product.Teams ? FillButton : StrokeButton;
|
|
76
|
+
return hideCTAButton ? null : /*#__PURE__*/_jsxs(Box, {
|
|
77
|
+
pt: 0,
|
|
78
|
+
display: "flex",
|
|
79
|
+
justifyContent: "center",
|
|
80
|
+
alignItems: "center",
|
|
81
|
+
flexDirection: isTeams && !simple ? 'row' : 'column',
|
|
82
|
+
gap: 8,
|
|
83
|
+
children: [/*#__PURE__*/_jsx(ButtonComponent, {
|
|
84
|
+
mt: 8,
|
|
85
|
+
disabled: product === Product.Silver && userHasSilver,
|
|
86
|
+
href: getCTAUrl({
|
|
87
|
+
productDetails,
|
|
88
|
+
product,
|
|
89
|
+
userHasSilver
|
|
90
|
+
}),
|
|
91
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
92
|
+
as: "span",
|
|
93
|
+
children: getCTATitle(product, !!productDetails?.isTrialPlan, userHasSilver)
|
|
94
|
+
})
|
|
95
|
+
}), isTeams ? /*#__PURE__*/_jsxs(_Fragment, {
|
|
96
|
+
children: [simple ? null : /*#__PURE__*/_jsx(Text, {
|
|
97
|
+
as: "span",
|
|
98
|
+
mt: 8,
|
|
99
|
+
children: ` or `
|
|
100
|
+
}), /*#__PURE__*/_jsx(FlexBox, {
|
|
101
|
+
mt: 8,
|
|
102
|
+
children: /*#__PURE__*/_jsx(StrokeButton, {
|
|
103
|
+
href: "/business/checkout?plan_type=directpurchase",
|
|
104
|
+
children: "Purchase now"
|
|
105
|
+
})
|
|
106
|
+
})]
|
|
107
|
+
}) : null]
|
|
43
108
|
});
|
|
44
109
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { PlansByType } from './config';
|
|
2
|
-
import {
|
|
2
|
+
import { AllCurrency } from './PricingCard/types';
|
|
3
|
+
import { User } from './types';
|
|
3
4
|
interface ProductsProps {
|
|
4
5
|
plansByType: PlansByType;
|
|
5
|
-
|
|
6
|
-
copyConfig?: CopyConfig;
|
|
7
|
-
user?: User;
|
|
6
|
+
user: User;
|
|
8
7
|
isUserInIndia: boolean;
|
|
8
|
+
currency: AllCurrency;
|
|
9
9
|
}
|
|
10
10
|
export declare const Products: React.FC<ProductsProps>;
|
|
11
11
|
export {};
|
|
@@ -5,10 +5,9 @@ import { Product } from './types';
|
|
|
5
5
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
6
|
export const Products = ({
|
|
7
7
|
plansByType,
|
|
8
|
-
ctaConfig,
|
|
9
|
-
copyConfig,
|
|
10
8
|
user,
|
|
11
|
-
isUserInIndia
|
|
9
|
+
isUserInIndia,
|
|
10
|
+
currency
|
|
12
11
|
}) => {
|
|
13
12
|
const productsLength = Object.keys(plansByType).length;
|
|
14
13
|
const renderCard = product => {
|
|
@@ -18,30 +17,45 @@ export const Products = ({
|
|
|
18
17
|
product: Product.Basic,
|
|
19
18
|
productDetails: getProductDetails(plansByType, product),
|
|
20
19
|
plansByType: plansByType,
|
|
21
|
-
isCurrentPlan: user && !user.anonymous && !user.proSilver && !user.proGold,
|
|
22
20
|
isUserInIndia: isUserInIndia,
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
currency: currency,
|
|
22
|
+
user: user
|
|
25
23
|
}, product);
|
|
26
24
|
case Product.Silver:
|
|
27
25
|
return /*#__PURE__*/_jsx(PricingCard, {
|
|
28
26
|
product: Product.Silver,
|
|
29
27
|
productDetails: getProductDetails(plansByType, product),
|
|
30
28
|
plansByType: plansByType,
|
|
31
|
-
isCurrentPlan: user?.proSilver,
|
|
32
29
|
isUserInIndia: isUserInIndia,
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
currency: currency,
|
|
31
|
+
user: user
|
|
35
32
|
}, product);
|
|
36
33
|
case Product.Gold:
|
|
37
34
|
return /*#__PURE__*/_jsx(PricingCard, {
|
|
38
35
|
product: Product.Gold,
|
|
39
36
|
productDetails: getProductDetails(plansByType, product),
|
|
40
37
|
plansByType: plansByType,
|
|
41
|
-
isCurrentPlan: user?.proGold,
|
|
42
38
|
isUserInIndia: isUserInIndia,
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
currency: currency,
|
|
40
|
+
user: user
|
|
41
|
+
}, product);
|
|
42
|
+
case Product.Teams:
|
|
43
|
+
return /*#__PURE__*/_jsx(PricingCard, {
|
|
44
|
+
product: Product.Teams,
|
|
45
|
+
productDetails: getProductDetails(plansByType, product),
|
|
46
|
+
plansByType: plansByType,
|
|
47
|
+
isUserInIndia: isUserInIndia,
|
|
48
|
+
currency: currency,
|
|
49
|
+
user: user
|
|
50
|
+
}, product);
|
|
51
|
+
case Product.Enterprise:
|
|
52
|
+
return /*#__PURE__*/_jsx(PricingCard, {
|
|
53
|
+
product: Product.Enterprise,
|
|
54
|
+
productDetails: getProductDetails(plansByType, product),
|
|
55
|
+
plansByType: plansByType,
|
|
56
|
+
isUserInIndia: isUserInIndia,
|
|
57
|
+
currency: currency,
|
|
58
|
+
user: user
|
|
45
59
|
}, product);
|
|
46
60
|
default:
|
|
47
61
|
return null;
|
|
@@ -49,7 +63,8 @@ export const Products = ({
|
|
|
49
63
|
};
|
|
50
64
|
return /*#__PURE__*/_jsx(GridBox, {
|
|
51
65
|
as: "ul",
|
|
52
|
-
pt:
|
|
66
|
+
pt: 16,
|
|
67
|
+
pb: 24,
|
|
53
68
|
px: 0,
|
|
54
69
|
mb: 0,
|
|
55
70
|
center: true,
|
|
@@ -2,7 +2,7 @@ import { Product, ProductDetails } from './types';
|
|
|
2
2
|
type Period = 'annual' | 'monthly';
|
|
3
3
|
type PlansByPeriod = Record<Period, ProductDetails>;
|
|
4
4
|
export type PlansByType = Record<Product, PlansByPeriod>;
|
|
5
|
-
export declare const getProductDescription: (product: Product) => "
|
|
5
|
+
export declare const getProductDescription: (product: Product) => "Start learning something new with basic access" | "Train your team with in-demand skills and flexible admin tools" | "Customizable training for your organization" | "Build in-demand technical skills for work or a personal project" | "Develop the skills and experience to land a job in tech";
|
|
6
6
|
export declare const getProductDetails: (products: PlansByType, product: Product) => ProductDetails;
|
|
7
7
|
export declare const groupPlansByType: (products: ProductDetails[]) => PlansByType;
|
|
8
8
|
export {};
|
|
@@ -4,7 +4,9 @@ export const getProductDescription = product => {
|
|
|
4
4
|
case Product.Basic:
|
|
5
5
|
return 'Start learning something new with basic access';
|
|
6
6
|
case Product.Teams:
|
|
7
|
-
return '';
|
|
7
|
+
return 'Train your team with in-demand skills and flexible admin tools';
|
|
8
|
+
case Product.Enterprise:
|
|
9
|
+
return 'Customizable training for your organization';
|
|
8
10
|
case Product.Pro:
|
|
9
11
|
case Product.Silver:
|
|
10
12
|
return 'Build in-demand technical skills for work or a personal project';
|
|
@@ -13,7 +15,7 @@ export const getProductDescription = product => {
|
|
|
13
15
|
}
|
|
14
16
|
};
|
|
15
17
|
export const getProductDetails = (products, product) => {
|
|
16
|
-
if (product === Product.Basic
|
|
18
|
+
if (product === Product.Basic) {
|
|
17
19
|
return products[product].monthly;
|
|
18
20
|
}
|
|
19
21
|
return products[product].annual;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { Background } from '@codecademy/gamut-styles';
|
|
2
|
-
import
|
|
2
|
+
import { AllCurrency } from './PricingCard/types';
|
|
3
|
+
import type { ProductDetails, User } from './types';
|
|
3
4
|
type PricingSectionProps = Omit<Partial<React.ComponentProps<typeof Background>>, 'title'> & {
|
|
4
5
|
products: ProductDetails[];
|
|
5
6
|
title?: React.ReactNode;
|
|
6
|
-
|
|
7
|
-
ctaConfig?: CtaConfig;
|
|
8
|
-
copyConfig?: CopyConfig;
|
|
9
|
-
user?: User;
|
|
7
|
+
user: User;
|
|
10
8
|
isUserInIndia: boolean;
|
|
9
|
+
currency: AllCurrency;
|
|
11
10
|
};
|
|
12
11
|
export declare const PricingSection: React.FC<PricingSectionProps>;
|
|
13
12
|
export {};
|
|
@@ -1,58 +1,39 @@
|
|
|
1
|
-
import { Box } from '@codecademy/gamut';
|
|
2
|
-
import {
|
|
1
|
+
import { Box, ContentContainer, Text } from '@codecademy/gamut';
|
|
2
|
+
import { CheckerLoose } from '@codecademy/gamut-patterns';
|
|
3
3
|
import { groupPlansByType } from './config';
|
|
4
4
|
import { Products } from './Products';
|
|
5
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
6
6
|
export const PricingSection = ({
|
|
7
7
|
products,
|
|
8
8
|
title,
|
|
9
|
-
planTypes,
|
|
10
|
-
ctaConfig,
|
|
11
|
-
copyConfig,
|
|
12
9
|
user,
|
|
13
10
|
isUserInIndia,
|
|
14
|
-
|
|
11
|
+
currency
|
|
15
12
|
}) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return isValidPlanType && !user.proSilver && !user.proGold;
|
|
24
|
-
}
|
|
25
|
-
if (product.planType === 'pro-silver') {
|
|
26
|
-
return isValidPlanType && !user.proGold;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return isValidPlanType;
|
|
30
|
-
});
|
|
31
|
-
return /*#__PURE__*/_jsx(Background, {
|
|
32
|
-
bg: "beige",
|
|
33
|
-
px: {
|
|
34
|
-
_: 16,
|
|
35
|
-
md: 32,
|
|
36
|
-
lg: 64,
|
|
37
|
-
xl: 96
|
|
38
|
-
},
|
|
39
|
-
mb: 48,
|
|
40
|
-
...bgProps,
|
|
41
|
-
children: /*#__PURE__*/_jsxs(Box, {
|
|
42
|
-
maxWidth: 1440,
|
|
43
|
-
px: {
|
|
44
|
-
_: 32,
|
|
45
|
-
lg: 64,
|
|
46
|
-
xl: 96
|
|
13
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
14
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
15
|
+
as: "h1",
|
|
16
|
+
textAlign: "center",
|
|
17
|
+
fontSize: {
|
|
18
|
+
_: 34,
|
|
19
|
+
md: 44
|
|
47
20
|
},
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
21
|
+
width: "100%",
|
|
22
|
+
mb: 16,
|
|
23
|
+
children: title
|
|
24
|
+
}), /*#__PURE__*/_jsxs(Box, {
|
|
25
|
+
position: "relative",
|
|
26
|
+
children: [/*#__PURE__*/_jsx(CheckerLoose, {
|
|
27
|
+
height: "100%",
|
|
28
|
+
position: "absolute"
|
|
29
|
+
}), /*#__PURE__*/_jsx(ContentContainer, {
|
|
30
|
+
children: /*#__PURE__*/_jsx(Products, {
|
|
31
|
+
plansByType: groupPlansByType(products),
|
|
32
|
+
user: user,
|
|
33
|
+
isUserInIndia: isUserInIndia,
|
|
34
|
+
currency: currency
|
|
35
|
+
})
|
|
55
36
|
})]
|
|
56
|
-
})
|
|
37
|
+
})]
|
|
57
38
|
});
|
|
58
39
|
};
|
|
@@ -3,7 +3,8 @@ export declare enum Product {
|
|
|
3
3
|
Pro = "pro",
|
|
4
4
|
Teams = "teams",
|
|
5
5
|
Silver = "pro-silver",
|
|
6
|
-
Gold = "pro-gold"
|
|
6
|
+
Gold = "pro-gold",
|
|
7
|
+
Enterprise = "enterprise"
|
|
7
8
|
}
|
|
8
9
|
export interface ProductDetails {
|
|
9
10
|
isTrialPlan?: boolean | null | undefined;
|
|
@@ -14,7 +15,7 @@ export interface ProductDetails {
|
|
|
14
15
|
savings?: string | null | undefined;
|
|
15
16
|
includedTaxRate?: string | null | undefined;
|
|
16
17
|
}
|
|
17
|
-
export type PlanType = 'basic' | 'pro-silver' | 'pro-gold' | 'teams';
|
|
18
|
+
export type PlanType = 'basic' | 'pro-silver' | 'pro-gold' | 'teams' | 'enterprise';
|
|
18
19
|
export type CtaConfig = Partial<Record<PlanType, {
|
|
19
20
|
label?: string;
|
|
20
21
|
href?: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codecademy/brand",
|
|
3
3
|
"description": "Brand component library for Codecademy",
|
|
4
|
-
"version": "3.6.0
|
|
4
|
+
"version": "3.6.0",
|
|
5
5
|
"author": "Codecademy Engineering <dev@codecademy.com>",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@emotion/is-prop-valid": "^1.2.1",
|