@cloud-ru/uikit-product-site-section 0.23.3
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/CHANGELOG.md +1406 -0
- package/LICENSE +201 -0
- package/README.md +335 -0
- package/package.json +70 -0
- package/src/components/SectionAccordion/SectionAccordion.tsx +99 -0
- package/src/components/SectionAccordion/index.ts +1 -0
- package/src/components/SectionAccordion/styles.module.scss +13 -0
- package/src/components/SectionAccordion/types.ts +11 -0
- package/src/components/SectionAccordion/utils.ts +29 -0
- package/src/components/SectionBasic/SectionBasic.tsx +157 -0
- package/src/components/SectionBasic/index.ts +1 -0
- package/src/components/SectionBasic/styles.module.scss +88 -0
- package/src/components/SectionBenefits/SectionBenefits.tsx +163 -0
- package/src/components/SectionBenefits/components/CardNumeric/CardNumeric.tsx +17 -0
- package/src/components/SectionBenefits/components/CardNumeric/index.ts +1 -0
- package/src/components/SectionBenefits/components/CardNumeric/styles.module.scss +6 -0
- package/src/components/SectionBenefits/components/index.ts +1 -0
- package/src/components/SectionBenefits/index.ts +1 -0
- package/src/components/SectionBenefits/styles.module.scss +15 -0
- package/src/components/SectionBenefits/types.ts +91 -0
- package/src/components/SectionBenefitsBanner/SectionBenefitsBanner.tsx +91 -0
- package/src/components/SectionBenefitsBanner/index.ts +1 -0
- package/src/components/SectionBenefitsBanner/styles.module.scss +119 -0
- package/src/components/SectionBenefitsBanner/types.ts +42 -0
- package/src/components/SectionBenefitsBanner/utils.ts +15 -0
- package/src/components/SectionBlogCarousel/SectionBlogCarousel.tsx +22 -0
- package/src/components/SectionBlogCarousel/index.ts +1 -0
- package/src/components/SectionBlogCarousel/utils.ts +29 -0
- package/src/components/SectionCaseCarousel/SectionCaseCarousel.tsx +22 -0
- package/src/components/SectionCaseCarousel/index.ts +1 -0
- package/src/components/SectionCaseCarousel/styles.module.scss +3 -0
- package/src/components/SectionCaseCarousel/utils.ts +24 -0
- package/src/components/SectionCatalog/SectionCatalog.tsx +105 -0
- package/src/components/SectionCatalog/constants.ts +5 -0
- package/src/components/SectionCatalog/index.ts +1 -0
- package/src/components/SectionCatalog/styles.module.scss +45 -0
- package/src/components/SectionClientsCarousel/SectionClientsCarousel.tsx +23 -0
- package/src/components/SectionClientsCarousel/index.ts +1 -0
- package/src/components/SectionClientsCarousel/utils.ts +29 -0
- package/src/components/SectionContent/SectionContent.tsx +98 -0
- package/src/components/SectionContent/index.ts +1 -0
- package/src/components/SectionContent/styles.module.scss +70 -0
- package/src/components/SectionContentList/SectionContentList.tsx +99 -0
- package/src/components/SectionContentList/index.ts +1 -0
- package/src/components/SectionContentList/styles.module.scss +56 -0
- package/src/components/SectionContentTabs/SectionContentTabs.tsx +156 -0
- package/src/components/SectionContentTabs/index.ts +1 -0
- package/src/components/SectionContentTabs/styles.module.scss +85 -0
- package/src/components/SectionExpertsCarousel/SectionExpertsCarousel.tsx +18 -0
- package/src/components/SectionExpertsCarousel/constants.ts +2 -0
- package/src/components/SectionExpertsCarousel/index.ts +1 -0
- package/src/components/SectionExpertsCarousel/types.ts +6 -0
- package/src/components/SectionLeading/SectionLeading.tsx +116 -0
- package/src/components/SectionLeading/index.ts +1 -0
- package/src/components/SectionLeading/styles.module.scss +30 -0
- package/src/components/SectionLeading/utils.ts +11 -0
- package/src/components/SectionMarketplaceCarousel/SectionMarketplaceCarousel.tsx +23 -0
- package/src/components/SectionMarketplaceCarousel/index.ts +1 -0
- package/src/components/SectionMarketplaceCarousel/utils.ts +33 -0
- package/src/components/SectionMedia/SectionMedia.tsx +57 -0
- package/src/components/SectionMedia/index.ts +1 -0
- package/src/components/SectionMedia/styles.module.scss +9 -0
- package/src/components/SectionPersonalManager/SectionPersonalManager.tsx +135 -0
- package/src/components/SectionPersonalManager/index.ts +1 -0
- package/src/components/SectionPersonalManager/styles.module.scss +146 -0
- package/src/components/SectionPersonalManager/utils.ts +15 -0
- package/src/components/SectionPromoList/SectionPromoList.tsx +66 -0
- package/src/components/SectionPromoList/index.ts +1 -0
- package/src/components/SectionPromoList/styles.module.scss +52 -0
- package/src/components/SectionSocial/SectionSocial.tsx +66 -0
- package/src/components/SectionSocial/constants.ts +5 -0
- package/src/components/SectionSocial/index.ts +1 -0
- package/src/components/SectionSocial/styles.module.scss +4 -0
- package/src/components/SectionTable/SectionTable.tsx +46 -0
- package/src/components/SectionTable/index.ts +1 -0
- package/src/components/SectionTable/styles.module.scss +19 -0
- package/src/components/index.ts +19 -0
- package/src/constants.ts +4 -0
- package/src/helperComponents/BenefitItem/BenefitItem.tsx +34 -0
- package/src/helperComponents/BenefitItem/index.ts +1 -0
- package/src/helperComponents/BenefitItem/styles.module.scss +34 -0
- package/src/helperComponents/BenefitItem/utils.ts +28 -0
- package/src/helperComponents/CardClient/CardClient.tsx +15 -0
- package/src/helperComponents/CardClient/index.ts +1 -0
- package/src/helperComponents/CardClient/styles.module.scss +25 -0
- package/src/helperComponents/CardLeading/CardLeading.tsx +29 -0
- package/src/helperComponents/CardLeading/index.ts +2 -0
- package/src/helperComponents/CardLeading/styles.module.scss +43 -0
- package/src/helperComponents/CardLeading/types.ts +12 -0
- package/src/helperComponents/CardLeading/utils.ts +28 -0
- package/src/helperComponents/CardSocial/CardSocial.tsx +105 -0
- package/src/helperComponents/CardSocial/index.ts +1 -0
- package/src/helperComponents/CardSocial/styles.module.scss +48 -0
- package/src/helperComponents/CardSocial/utils.ts +13 -0
- package/src/helperComponents/Expert/Expert.tsx +28 -0
- package/src/helperComponents/Expert/index.ts +1 -0
- package/src/helperComponents/Expert/styles.module.scss +39 -0
- package/src/helperComponents/PromoList/PromoList.tsx +26 -0
- package/src/helperComponents/PromoList/index.ts +1 -0
- package/src/helperComponents/PromoList/styles.module.scss +46 -0
- package/src/helperComponents/SectionButton/SectionButton.tsx +19 -0
- package/src/helperComponents/SectionButton/index.tsx +1 -0
- package/src/helperComponents/SectionButton/types.ts +9 -0
- package/src/helperComponents/SectionCarousel/SectionCarousel.tsx +109 -0
- package/src/helperComponents/SectionCarousel/index.ts +2 -0
- package/src/helperComponents/SectionCarousel/styles.module.scss +8 -0
- package/src/helperComponents/SectionCarousel/types.ts +42 -0
- package/src/helperComponents/SectionCarousel/utils.ts +10 -0
- package/src/helperComponents/SectionCatalogFooter/SectionCatalogFooter.tsx +29 -0
- package/src/helperComponents/SectionCatalogFooter/index.ts +1 -0
- package/src/helperComponents/SectionCatalogFooter/styles.module.scss +10 -0
- package/src/helperComponents/SectionTitle/SectionTitle.tsx +72 -0
- package/src/helperComponents/SectionTitle/constants.ts +5 -0
- package/src/helperComponents/SectionTitle/index.ts +1 -0
- package/src/helperComponents/SectionTitle/styles.module.scss +33 -0
- package/src/helperComponents/SectionTitle/types.ts +7 -0
- package/src/helperComponents/SectionTitle/utils.ts +83 -0
- package/src/helperComponents/index.ts +10 -0
- package/src/index.ts +2 -0
- package/src/types.ts +23 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import cn from 'classnames';
|
|
2
|
+
|
|
3
|
+
import { Typography } from '@snack-uikit/typography';
|
|
4
|
+
|
|
5
|
+
import { ExpertDetails } from '../../components/SectionExpertsCarousel/types';
|
|
6
|
+
import styles from './styles.module.scss';
|
|
7
|
+
|
|
8
|
+
export type ExpertProps = ExpertDetails & {
|
|
9
|
+
className?: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function Expert({ image, name, surname, jobTitle, className }: ExpertProps) {
|
|
13
|
+
return (
|
|
14
|
+
<div className={cn(styles.expert, className)}>
|
|
15
|
+
<div className={styles.imageWrapper}>
|
|
16
|
+
<div className={styles.imageBackground}></div>
|
|
17
|
+
<img src={image} alt='expert' className={styles.image} />
|
|
18
|
+
</div>
|
|
19
|
+
<div className={styles.personalDetails}>
|
|
20
|
+
<Typography.SansTitleL className={styles.detailsColor}>{name}</Typography.SansTitleL>
|
|
21
|
+
<Typography.SansTitleL className={styles.detailsColor}>{surname}</Typography.SansTitleL>
|
|
22
|
+
</div>
|
|
23
|
+
<div className={styles.jobTitle}>
|
|
24
|
+
<Typography.SansBodyM className={styles.detailsColor}>{jobTitle}</Typography.SansBodyM>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Expert';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
@use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as var;
|
|
2
|
+
|
|
3
|
+
.expert {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
gap: var.$dimension-1m;
|
|
7
|
+
overflow: hidden;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.imageWrapper {
|
|
11
|
+
display: flex;
|
|
12
|
+
justify-content: center;
|
|
13
|
+
position: relative;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.imageBackground {
|
|
17
|
+
position: absolute;
|
|
18
|
+
width: 100%;
|
|
19
|
+
height: 100%;
|
|
20
|
+
background-color: var.$sys-neutral-accent-default;
|
|
21
|
+
opacity: 0.08;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.personalDetails,
|
|
25
|
+
.jobTitle {
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.detailsColor {
|
|
31
|
+
color: var.$sys-neutral-text-main;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.image {
|
|
35
|
+
position: relative;
|
|
36
|
+
height: 290px;
|
|
37
|
+
object-fit: cover;
|
|
38
|
+
pointer-events: none;
|
|
39
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { DecorCheckedSVG } from '@cloud-ru/uikit-product-icons';
|
|
2
|
+
import { RichText } from '@cloud-ru/uikit-product-site-rich-text';
|
|
3
|
+
import { WithLayoutType } from '@cloud-ru/uikit-product-utils';
|
|
4
|
+
|
|
5
|
+
import styles from './styles.module.scss';
|
|
6
|
+
|
|
7
|
+
export type PromoListProps = { title: string; items: string[] };
|
|
8
|
+
|
|
9
|
+
export function PromoList({ title, items, layoutType }: WithLayoutType<PromoListProps>) {
|
|
10
|
+
return (
|
|
11
|
+
<div className={styles.promoList} data-layout-type={layoutType}>
|
|
12
|
+
<div className={styles.title} data-layout-type={layoutType} data-test-id='promo-list__card_title'>
|
|
13
|
+
<RichText richText={title} />
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<ul className={styles.list}>
|
|
17
|
+
{items.map(item => (
|
|
18
|
+
<li className={styles.listItem} key={item}>
|
|
19
|
+
<DecorCheckedSVG className={styles.listItemIcon} />
|
|
20
|
+
<RichText richText={item} />
|
|
21
|
+
</li>
|
|
22
|
+
))}
|
|
23
|
+
</ul>
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './PromoList';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
@use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as var;
|
|
2
|
+
|
|
3
|
+
.promoList {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
gap: 16px;
|
|
7
|
+
color: var.$sys-invert-neutral-text-main;
|
|
8
|
+
|
|
9
|
+
position: relative;
|
|
10
|
+
|
|
11
|
+
max-width: 480px;
|
|
12
|
+
|
|
13
|
+
&[data-layout-type='mobile'] {
|
|
14
|
+
max-width: 100%;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.title {
|
|
19
|
+
@include var.composite-var(var.$sans-headline-s);
|
|
20
|
+
|
|
21
|
+
&[data-layout-type='tablet'],
|
|
22
|
+
&[data-layout-type='mobile'] {
|
|
23
|
+
@include var.composite-var(var.$sans-title-l);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.list {
|
|
28
|
+
list-style: none;
|
|
29
|
+
padding: 0;
|
|
30
|
+
margin: 0;
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
gap: 16px;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.listItem {
|
|
37
|
+
@include var.composite-var(var.$sans-body-m);
|
|
38
|
+
|
|
39
|
+
display: flex;
|
|
40
|
+
gap: 8px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.listItemIcon {
|
|
44
|
+
color: var.$sys-invert-neutral-accent-default;
|
|
45
|
+
flex-shrink: 0;
|
|
46
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ArrowLinksSVG } from '@cloud-ru/uikit-product-icons';
|
|
2
|
+
import { ButtonFilled, ButtonOutline } from '@snack-uikit/button';
|
|
3
|
+
import { Link } from '@snack-uikit/link';
|
|
4
|
+
|
|
5
|
+
import { SectionButtonProps } from './types';
|
|
6
|
+
|
|
7
|
+
export function SectionButton(button: SectionButtonProps) {
|
|
8
|
+
const { type, ...buttonProps } = button;
|
|
9
|
+
|
|
10
|
+
if (button.href) {
|
|
11
|
+
return <Link key={button.label} {...buttonProps} text={button.label} size='l' insideText />;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (type === 'outline') {
|
|
15
|
+
return <ButtonOutline key={button.label} size='l' appearance='neutral' icon={<ArrowLinksSVG />} {...buttonProps} />;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return <ButtonFilled key={button.label} size='l' {...buttonProps} />;
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './SectionButton';
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import debounce from 'lodash.debounce';
|
|
2
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
import { extractSupportProps } from '@cloud-ru/uikit-product-utils';
|
|
5
|
+
import { Carousel } from '@snack-uikit/carousel';
|
|
6
|
+
|
|
7
|
+
import { SectionBasic } from '../../components';
|
|
8
|
+
import { SECTION_COLORS } from '../../constants';
|
|
9
|
+
import styles from './styles.module.scss';
|
|
10
|
+
import { SectionCarouselProps } from './types';
|
|
11
|
+
import { calculateAmountOfItemsPerPage } from './utils';
|
|
12
|
+
|
|
13
|
+
const MOBILE_LAYOUTS = ['tablet', 'mobile'];
|
|
14
|
+
|
|
15
|
+
export function SectionCarousel({
|
|
16
|
+
id,
|
|
17
|
+
title,
|
|
18
|
+
titleTag,
|
|
19
|
+
subtitle,
|
|
20
|
+
subtitleTag,
|
|
21
|
+
titleSectionSize,
|
|
22
|
+
description,
|
|
23
|
+
children,
|
|
24
|
+
itemMinWidth,
|
|
25
|
+
maxItemsPerPage,
|
|
26
|
+
backgroundColor = SECTION_COLORS.NeutralBackground1Level,
|
|
27
|
+
className,
|
|
28
|
+
layoutType,
|
|
29
|
+
gap,
|
|
30
|
+
moreButton,
|
|
31
|
+
autoSwipe = 9,
|
|
32
|
+
infiniteScroll = true,
|
|
33
|
+
...rest
|
|
34
|
+
}: SectionCarouselProps) {
|
|
35
|
+
const [currentPage, setCurrentPage] = useState<number>(0);
|
|
36
|
+
const [itemsPerPageAmount, setItemsPerPageAmount] = useState<number>(0);
|
|
37
|
+
|
|
38
|
+
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const node = wrapperRef.current;
|
|
42
|
+
if (!node) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const calculateAmountOfItems = () => {
|
|
47
|
+
const wrapperWidth = wrapperRef.current?.offsetWidth;
|
|
48
|
+
if (!wrapperWidth) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
setItemsPerPageAmount(
|
|
53
|
+
calculateAmountOfItemsPerPage({
|
|
54
|
+
wrapperWidth,
|
|
55
|
+
itemMinWidth,
|
|
56
|
+
maxItemsPerPage,
|
|
57
|
+
}),
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const observer = new ResizeObserver(debounce(calculateAmountOfItems, 100));
|
|
62
|
+
observer.observe(node);
|
|
63
|
+
return () => observer.disconnect();
|
|
64
|
+
}, [itemMinWidth, maxItemsPerPage]);
|
|
65
|
+
|
|
66
|
+
const showArrows = useMemo(() => {
|
|
67
|
+
if (MOBILE_LAYOUTS.includes(layoutType)) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return children.length > itemsPerPageAmount;
|
|
72
|
+
}, [children.length, itemsPerPageAmount, layoutType]);
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<SectionBasic
|
|
76
|
+
id={id}
|
|
77
|
+
layoutType={layoutType}
|
|
78
|
+
className={className}
|
|
79
|
+
data-section-background={backgroundColor}
|
|
80
|
+
title={title}
|
|
81
|
+
titleTag={titleTag}
|
|
82
|
+
subtitle={subtitle}
|
|
83
|
+
subtitleTag={subtitleTag}
|
|
84
|
+
titleSectionSize={titleSectionSize}
|
|
85
|
+
description={description}
|
|
86
|
+
backgroundColor={backgroundColor}
|
|
87
|
+
moreButton={moreButton}
|
|
88
|
+
{...extractSupportProps(rest)}
|
|
89
|
+
>
|
|
90
|
+
<div ref={wrapperRef} className={styles.sectionCarousel} data-layout-type={layoutType}>
|
|
91
|
+
{itemsPerPageAmount > 0 && (
|
|
92
|
+
<Carousel
|
|
93
|
+
state={{ page: currentPage, onChange: setCurrentPage }}
|
|
94
|
+
arrows={showArrows}
|
|
95
|
+
controlsVisibility='always'
|
|
96
|
+
showItems={itemsPerPageAmount}
|
|
97
|
+
pagination={children.length > itemsPerPageAmount}
|
|
98
|
+
swipe={children.length > itemsPerPageAmount}
|
|
99
|
+
gap={gap}
|
|
100
|
+
autoSwipe={infiniteScroll ? autoSwipe : undefined}
|
|
101
|
+
infiniteScroll={infiniteScroll}
|
|
102
|
+
>
|
|
103
|
+
{children}
|
|
104
|
+
</Carousel>
|
|
105
|
+
)}
|
|
106
|
+
</div>
|
|
107
|
+
</SectionBasic>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
|
|
3
|
+
import { WithLayoutType, WithSupportProps } from '@cloud-ru/uikit-product-utils';
|
|
4
|
+
import { CarouselProps } from '@snack-uikit/carousel';
|
|
5
|
+
|
|
6
|
+
import { SectionBasicProps } from '../../components';
|
|
7
|
+
import { SectionColor } from '../../types';
|
|
8
|
+
import { SectionTitleProps } from '../SectionTitle';
|
|
9
|
+
|
|
10
|
+
type CarouselSlideConfig = {
|
|
11
|
+
/** Массив повторяющихся айтмов, из которых состоят слайды карусели */
|
|
12
|
+
children: ReactElement[];
|
|
13
|
+
/** Минимальная ширина айтема */
|
|
14
|
+
itemMinWidth: number;
|
|
15
|
+
/** Максимальное количество айтемов на слайде */
|
|
16
|
+
maxItemsPerPage: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type SectionCarouselProps = WithSupportProps<
|
|
20
|
+
WithLayoutType<
|
|
21
|
+
SectionTitleProps &
|
|
22
|
+
CarouselSlideConfig & {
|
|
23
|
+
/** id секции */
|
|
24
|
+
id?: string;
|
|
25
|
+
/** Цвет фона */
|
|
26
|
+
backgroundColor?: SectionColor;
|
|
27
|
+
/** CSS - класснейм */
|
|
28
|
+
className?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Автоматическое переключение слайдов в секундах
|
|
31
|
+
* @default 9
|
|
32
|
+
*/
|
|
33
|
+
autoSwipe?: number;
|
|
34
|
+
} & Pick<CarouselProps, 'gap' | 'autoSwipe' | 'infiniteScroll'> &
|
|
35
|
+
Pick<SectionBasicProps, 'moreButton'>
|
|
36
|
+
>
|
|
37
|
+
>;
|
|
38
|
+
|
|
39
|
+
export type LimitedSectionCarouselProps<T extends object> = Omit<SectionCarouselProps, keyof CarouselSlideConfig> & {
|
|
40
|
+
/** Массив айтемов */
|
|
41
|
+
items: T[];
|
|
42
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SectionCarouselProps } from './types';
|
|
2
|
+
|
|
3
|
+
type Props = Pick<SectionCarouselProps, 'itemMinWidth' | 'maxItemsPerPage'> & {
|
|
4
|
+
wrapperWidth: number;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const calculateAmountOfItemsPerPage = ({ wrapperWidth, itemMinWidth, maxItemsPerPage }: Props): number => {
|
|
8
|
+
const amount = Math.floor(wrapperWidth / itemMinWidth);
|
|
9
|
+
return amount > maxItemsPerPage ? maxItemsPerPage : amount;
|
|
10
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ChevronRightSVG } from '@cloud-ru/uikit-product-icons';
|
|
2
|
+
import { WithLayoutType } from '@cloud-ru/uikit-product-utils';
|
|
3
|
+
import { ButtonFunction, ButtonFunctionProps } from '@snack-uikit/button';
|
|
4
|
+
|
|
5
|
+
import styles from './styles.module.scss';
|
|
6
|
+
|
|
7
|
+
type FooterItem = {
|
|
8
|
+
label: string;
|
|
9
|
+
href?: string;
|
|
10
|
+
onClick?: ButtonFunctionProps['onClick'];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type SectionCatalogFooterProps = WithLayoutType<{
|
|
14
|
+
items: FooterItem[];
|
|
15
|
+
}>;
|
|
16
|
+
|
|
17
|
+
export function SectionCatalogFooter({ items, layoutType }: SectionCatalogFooterProps) {
|
|
18
|
+
if (items.length === 0) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div className={styles.footer} data-layout-type={layoutType}>
|
|
24
|
+
{items.map(({ label, onClick, href }) => (
|
|
25
|
+
<ButtonFunction key={label} label={label} size='m' onClick={onClick} href={href} icon={<ChevronRightSVG />} />
|
|
26
|
+
))}
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './SectionCatalogFooter';
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
import { RichText } from '@cloud-ru/uikit-product-site-rich-text';
|
|
4
|
+
import { WithLayoutType } from '@cloud-ru/uikit-product-utils';
|
|
5
|
+
import { Link, PickLinkProps } from '@snack-uikit/link';
|
|
6
|
+
import { Typography } from '@snack-uikit/typography';
|
|
7
|
+
|
|
8
|
+
import styles from './styles.module.scss';
|
|
9
|
+
import { SectionTag, Size } from './types';
|
|
10
|
+
import { getTitleTypographyProps } from './utils';
|
|
11
|
+
|
|
12
|
+
export type SectionTitleProps = WithLayoutType<{
|
|
13
|
+
/** Название секции */
|
|
14
|
+
title?: string;
|
|
15
|
+
/** Подзаголовок секции */
|
|
16
|
+
subtitle?: string;
|
|
17
|
+
/** Ссылка в названии */
|
|
18
|
+
titleLink?: PickLinkProps<typeof Link, 'href' | 'onClick' | 'target' | 'appearance' | 'textMode'>;
|
|
19
|
+
/** Описание секции */
|
|
20
|
+
description?: string;
|
|
21
|
+
/** Размер шрифтов заголовка и подзаголовка */
|
|
22
|
+
titleSectionSize?: Size;
|
|
23
|
+
/** Тег заголовка */
|
|
24
|
+
titleTag?: SectionTag;
|
|
25
|
+
/** Тег подзаголовка */
|
|
26
|
+
subtitleTag?: SectionTag;
|
|
27
|
+
/** Выравнивание текста */
|
|
28
|
+
titleAlign?: 'left' | 'center';
|
|
29
|
+
}>;
|
|
30
|
+
|
|
31
|
+
export function SectionTitle({
|
|
32
|
+
title,
|
|
33
|
+
subtitle,
|
|
34
|
+
titleLink,
|
|
35
|
+
description,
|
|
36
|
+
titleSectionSize = 'm',
|
|
37
|
+
titleTag = 'h2',
|
|
38
|
+
subtitleTag = 'h3',
|
|
39
|
+
layoutType,
|
|
40
|
+
titleAlign = 'left',
|
|
41
|
+
}: SectionTitleProps) {
|
|
42
|
+
const titleProps = useMemo(
|
|
43
|
+
() => getTitleTypographyProps({ titleSectionSize, layoutType }),
|
|
44
|
+
[layoutType, titleSectionSize],
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<>
|
|
49
|
+
{(title || description) && (
|
|
50
|
+
<div className={styles.sectionTitle} data-align={titleAlign}>
|
|
51
|
+
<div className={styles.titlesWrapper} data-align={titleAlign}>
|
|
52
|
+
{title && (
|
|
53
|
+
<Typography family='sans' {...titleProps} tag={titleTag} className={styles.title}>
|
|
54
|
+
{titleLink ? <Link {...titleLink} {...titleProps} text={title} /> : <RichText richText={title} />}
|
|
55
|
+
</Typography>
|
|
56
|
+
)}
|
|
57
|
+
{subtitle && (
|
|
58
|
+
<Typography family='sans' purpose='label' size='l' tag={subtitleTag} className={styles.subtitle}>
|
|
59
|
+
<RichText richText={subtitle} />
|
|
60
|
+
</Typography>
|
|
61
|
+
)}
|
|
62
|
+
</div>
|
|
63
|
+
{description && (
|
|
64
|
+
<Typography.SansBodyL className={styles.description}>
|
|
65
|
+
<RichText richText={description} />
|
|
66
|
+
</Typography.SansBodyL>
|
|
67
|
+
)}
|
|
68
|
+
</div>
|
|
69
|
+
)}
|
|
70
|
+
</>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './SectionTitle';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
@use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as var;
|
|
2
|
+
|
|
3
|
+
.sectionTitle,
|
|
4
|
+
.titlesWrapper {
|
|
5
|
+
display: flex;
|
|
6
|
+
gap: var.$dimension-1m;
|
|
7
|
+
text-align: left;
|
|
8
|
+
|
|
9
|
+
&[data-align='center'] {
|
|
10
|
+
text-align: center;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.sectionTitle {
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.titlesWrapper {
|
|
19
|
+
flex-direction: column-reverse;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.title {
|
|
23
|
+
color: var.$sys-neutral-text-main;
|
|
24
|
+
white-space: pre-line;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.subtitle {
|
|
28
|
+
color: var.$sys-neutral-text-light;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.description {
|
|
32
|
+
color: var.$sys-neutral-text-support;
|
|
33
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { WithLayoutType } from '@cloud-ru/uikit-product-utils';
|
|
2
|
+
import { TypographyProps } from '@snack-uikit/typography';
|
|
3
|
+
|
|
4
|
+
import { Size } from './types';
|
|
5
|
+
|
|
6
|
+
type Props = WithLayoutType<{
|
|
7
|
+
titleSectionSize: Size;
|
|
8
|
+
}>;
|
|
9
|
+
|
|
10
|
+
export const getTitleTypographyProps = ({
|
|
11
|
+
layoutType,
|
|
12
|
+
titleSectionSize,
|
|
13
|
+
}: Props): Pick<TypographyProps, 'size' | 'purpose'> => {
|
|
14
|
+
switch (layoutType) {
|
|
15
|
+
case 'tablet':
|
|
16
|
+
switch (titleSectionSize) {
|
|
17
|
+
case 'l':
|
|
18
|
+
return {
|
|
19
|
+
purpose: 'headline',
|
|
20
|
+
size: 'l',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
case 's':
|
|
24
|
+
return {
|
|
25
|
+
purpose: 'title',
|
|
26
|
+
size: 'l',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
case 'm':
|
|
30
|
+
default:
|
|
31
|
+
return {
|
|
32
|
+
purpose: 'headline',
|
|
33
|
+
size: 'm',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
case 'mobile':
|
|
38
|
+
switch (titleSectionSize) {
|
|
39
|
+
case 'l':
|
|
40
|
+
return {
|
|
41
|
+
purpose: 'headline',
|
|
42
|
+
size: 'm',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
case 's':
|
|
46
|
+
return {
|
|
47
|
+
purpose: 'title',
|
|
48
|
+
size: 'm',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
case 'm':
|
|
52
|
+
default:
|
|
53
|
+
return {
|
|
54
|
+
purpose: 'headline',
|
|
55
|
+
size: 's',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
case 'desktop':
|
|
60
|
+
case 'desktopSmall':
|
|
61
|
+
default:
|
|
62
|
+
switch (titleSectionSize) {
|
|
63
|
+
case 'l':
|
|
64
|
+
return {
|
|
65
|
+
purpose: 'display',
|
|
66
|
+
size: 'm',
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
case 's':
|
|
70
|
+
return {
|
|
71
|
+
purpose: 'headline',
|
|
72
|
+
size: 's',
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
case 'm':
|
|
76
|
+
default:
|
|
77
|
+
return {
|
|
78
|
+
purpose: 'headline',
|
|
79
|
+
size: 'l',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './CardLeading';
|
|
2
|
+
export * from './CardSocial';
|
|
3
|
+
export * from './Expert';
|
|
4
|
+
export * from './PromoList';
|
|
5
|
+
export * from './SectionCatalogFooter';
|
|
6
|
+
export * from './SectionTitle';
|
|
7
|
+
export * from './SectionCarousel';
|
|
8
|
+
export * from './CardClient';
|
|
9
|
+
export * from './BenefitItem';
|
|
10
|
+
export * from './SectionButton';
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SiteVideoProps } from '@cloud-ru/uikit-product-site-media';
|
|
2
|
+
import { ValueOf } from '@snack-uikit/utils';
|
|
3
|
+
|
|
4
|
+
import { SECTION_COLORS } from './constants';
|
|
5
|
+
|
|
6
|
+
export type SectionColor = ValueOf<typeof SECTION_COLORS>;
|
|
7
|
+
|
|
8
|
+
type MediaVideoProps = Pick<SiteVideoProps, 'video' | 'onPlay' | 'onError'> & {
|
|
9
|
+
image?: never;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type MediaImageProps = {
|
|
13
|
+
video?: never;
|
|
14
|
+
onPlay?: never;
|
|
15
|
+
onError?: never;
|
|
16
|
+
/** Ссылка на изображение */
|
|
17
|
+
image: {
|
|
18
|
+
src: string;
|
|
19
|
+
alt?: string;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type MediaContentProps = MediaImageProps | MediaVideoProps;
|