@cloud-ru/uikit-product-site-hero 0.5.40

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 (58) hide show
  1. package/CHANGELOG.md +937 -0
  2. package/LICENSE +201 -0
  3. package/README.md +71 -0
  4. package/package.json +61 -0
  5. package/src/components/HeroEvent/HeroEvent.tsx +108 -0
  6. package/src/components/HeroEvent/constants.ts +23 -0
  7. package/src/components/HeroEvent/index.ts +1 -0
  8. package/src/components/HeroEvent/styles.module.scss +147 -0
  9. package/src/components/HeroEvent/types.ts +6 -0
  10. package/src/components/HeroMain/HeroMain.tsx +159 -0
  11. package/src/components/HeroMain/components/PlatformLink/PlatformLink.tsx +31 -0
  12. package/src/components/HeroMain/components/PlatformLink/index.ts +1 -0
  13. package/src/components/HeroMain/components/index.ts +1 -0
  14. package/src/components/HeroMain/index.ts +1 -0
  15. package/src/components/HeroMain/styles.module.scss +154 -0
  16. package/src/components/HeroMain/utils.ts +17 -0
  17. package/src/components/HeroSlider/HeroSlider.tsx +72 -0
  18. package/src/components/HeroSlider/components/HeroSlide/HeroSlide.tsx +70 -0
  19. package/src/components/HeroSlider/components/HeroSlide/constants.ts +12 -0
  20. package/src/components/HeroSlider/components/HeroSlide/index.ts +2 -0
  21. package/src/components/HeroSlider/components/HeroSlide/styles.module.scss +164 -0
  22. package/src/components/HeroSlider/components/HeroSlide/types.ts +39 -0
  23. package/src/components/HeroSlider/components/HeroSlide/util.ts +35 -0
  24. package/src/components/HeroSlider/components/HeroSlideImage/HeroSlideImage.tsx +29 -0
  25. package/src/components/HeroSlider/components/HeroSlideImage/index.ts +1 -0
  26. package/src/components/HeroSlider/components/HeroSlideImage/styles.module.scss +31 -0
  27. package/src/components/HeroSlider/components/HeroSlideImageBg/HeroSlideImageBg.tsx +31 -0
  28. package/src/components/HeroSlider/components/HeroSlideImageBg/index.ts +1 -0
  29. package/src/components/HeroSlider/components/HeroSlideImageBg/styles.module.scss +20 -0
  30. package/src/components/HeroSlider/components/HeroSlideMedia/HeroSlideMedia.tsx +22 -0
  31. package/src/components/HeroSlider/components/HeroSlideMedia/index.ts +2 -0
  32. package/src/components/HeroSlider/components/HeroSlideMedia/types.ts +17 -0
  33. package/src/components/HeroSlider/components/HeroSlideVideoBg/HTMLComment.tsx +36 -0
  34. package/src/components/HeroSlider/components/HeroSlideVideoBg/HeroSlideVideoBg.tsx +30 -0
  35. package/src/components/HeroSlider/components/HeroSlideVideoBg/index.ts +1 -0
  36. package/src/components/HeroSlider/components/index.ts +5 -0
  37. package/src/components/HeroSlider/index.ts +2 -0
  38. package/src/components/HeroSlider/styles.module.scss +41 -0
  39. package/src/components/HeroZero/HeroZero.tsx +84 -0
  40. package/src/components/HeroZero/index.ts +1 -0
  41. package/src/components/HeroZero/styles.module.scss +111 -0
  42. package/src/components/HeroZero/utils.ts +15 -0
  43. package/src/components/index.ts +4 -0
  44. package/src/constants.ts +12 -0
  45. package/src/helperComponents/HeroEventButton/HeroEventButton.tsx +32 -0
  46. package/src/helperComponents/HeroEventButton/constants.ts +21 -0
  47. package/src/helperComponents/HeroEventButton/index.ts +1 -0
  48. package/src/helperComponents/HeroEventButton/types.ts +5 -0
  49. package/src/helperComponents/HeroNavbar/HeroNavbar.tsx +26 -0
  50. package/src/helperComponents/HeroNavbar/index.ts +1 -0
  51. package/src/helperComponents/HeroNavbar/styles.module.scss +13 -0
  52. package/src/helperComponents/Place/Place.tsx +32 -0
  53. package/src/helperComponents/Place/constants.ts +34 -0
  54. package/src/helperComponents/Place/index.ts +1 -0
  55. package/src/helperComponents/Place/styles.module.scss +3 -0
  56. package/src/helperComponents/index.tsx +3 -0
  57. package/src/index.ts +1 -0
  58. package/src/types.ts +5 -0
@@ -0,0 +1,39 @@
1
+ import { ButtonPromoProps } from '@cloud-ru/uikit-product-button-predefined';
2
+ import { EridProps } from '@cloud-ru/uikit-product-site-tag';
3
+ import { ValueOf } from '@snack-uikit/utils';
4
+
5
+ import { HeroSlideMediaProps } from '../HeroSlideMedia';
6
+ import { Appearance, Color } from './constants';
7
+
8
+ type ColorType = ValueOf<typeof Color>;
9
+
10
+ type AppearanceType = ValueOf<typeof Appearance>;
11
+
12
+ export type HeroSlideBaseProps = {
13
+ /** id компонента */
14
+ id?: string;
15
+ /** Заголовок*/
16
+ title: string;
17
+ /** Описание */
18
+ description?: string;
19
+ /** Медиа-контент */
20
+ media: HeroSlideMediaProps;
21
+ /** Кнопка ButtonPromo */
22
+ button: Omit<ButtonPromoProps, 'size' | 'appearance' | 'className'>;
23
+ /** Плашка рекламы с tooltip */
24
+ erid?: Pick<EridProps, 'tip' | 'appearance'>;
25
+ /** CSS-класс */
26
+ className?: string;
27
+ };
28
+
29
+ type HeroSlideWithColor = HeroSlideBaseProps & {
30
+ appearance: Exclude<AppearanceType, 'brand' | 'graphite'>;
31
+ color: ColorType;
32
+ };
33
+
34
+ type HeroSlideWithoutColor = HeroSlideBaseProps & {
35
+ appearance: Exclude<AppearanceType, 'decor'>;
36
+ color?: never;
37
+ };
38
+
39
+ export type HeroSlideProps = HeroSlideWithColor | HeroSlideWithoutColor;
@@ -0,0 +1,35 @@
1
+ import { LayoutType } from '@cloud-ru/uikit-product-utils';
2
+ import { TypographyProps } from '@snack-uikit/typography';
3
+
4
+ import { HeroSlideImageProps } from '../HeroSlideImage';
5
+ import { HeroSlideBaseProps } from './types';
6
+
7
+ export const getTitleProps = (layoutType: LayoutType): Pick<TypographyProps, 'purpose' | 'size'> => {
8
+ switch (layoutType) {
9
+ case 'mobile':
10
+ case 'tablet':
11
+ return {
12
+ purpose: 'headline',
13
+ size: 'l',
14
+ };
15
+ default:
16
+ return {
17
+ purpose: 'display',
18
+ size: 'm',
19
+ };
20
+ }
21
+ };
22
+
23
+ export const getSliderContentWrapperImageType = (
24
+ media: HeroSlideBaseProps['media'],
25
+ ): HeroSlideImageProps['format'] | undefined => {
26
+ switch (media.type) {
27
+ case 'image':
28
+ return media.format;
29
+
30
+ case 'imageBg':
31
+ case 'videoBg':
32
+ default:
33
+ return undefined;
34
+ }
35
+ };
@@ -0,0 +1,29 @@
1
+ import { CSS_BREAKPOINTS, WithLayoutType } from '@cloud-ru/uikit-product-utils';
2
+
3
+ import styles from './styles.module.scss';
4
+
5
+ export type HeroSlideImageProps = {
6
+ /** Ссылки на картинку */
7
+ source: {
8
+ desktop: string;
9
+ tablet?: string;
10
+ };
11
+ /** Форма картинки */
12
+ format: 'rectangle' | 'square' | 'custom';
13
+ };
14
+
15
+ export function HeroSlideImage({ source, format, layoutType }: WithLayoutType<HeroSlideImageProps>) {
16
+ const { tablet, desktop } = source;
17
+
18
+ if (layoutType === 'mobile') {
19
+ return null;
20
+ }
21
+
22
+ return (
23
+ <picture className={styles.imageWrapper} data-image-format={format} data-layout-type={layoutType}>
24
+ {tablet && <source srcSet={tablet} media={CSS_BREAKPOINTS.tablet} />}
25
+ <source srcSet={desktop} media={CSS_BREAKPOINTS.large} />
26
+ <img src={desktop} className={styles.image} data-image-format={format} loading='lazy' alt='main slide' />
27
+ </picture>
28
+ );
29
+ }
@@ -0,0 +1 @@
1
+ export * from './HeroSlideImage';
@@ -0,0 +1,31 @@
1
+ $rectangle: 'rectangle';
2
+ $square: 'square';
3
+
4
+ .imageWrapper {
5
+ display: flex;
6
+ align-items: center;
7
+ height: 100%;
8
+
9
+ &[data-image-format='#{$rectangle}'] {
10
+ &[data-layout-type='desktop'] {
11
+ flex-shrink: 0;
12
+ }
13
+ }
14
+ }
15
+
16
+ .image {
17
+ height: 100%;
18
+ object-fit: cover;
19
+ object-position: center;
20
+
21
+ pointer-events: none;
22
+
23
+ &[data-image-format='#{$rectangle}'] {
24
+ width: auto;
25
+ max-height: 328px;
26
+ }
27
+
28
+ &[data-image-format='#{$square}'] {
29
+ max-height: 368px;
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ import { CSS_BREAKPOINTS, WithLayoutType } from '@cloud-ru/uikit-product-utils';
2
+
3
+ import styles from './styles.module.scss';
4
+
5
+ export type HeroSlideImageBgProps = {
6
+ /** Ссылки на картинку-фон */
7
+ source: {
8
+ desktopLg?: string;
9
+ desktop: string;
10
+ tablet: string;
11
+ mobile: string;
12
+ };
13
+ };
14
+
15
+ export function HeroSlideImageBg({ source }: WithLayoutType<HeroSlideImageBgProps>) {
16
+ return (
17
+ <picture className={styles.backgroundImageWrapper}>
18
+ <source srcSet={source.mobile} media={CSS_BREAKPOINTS.mobile} />
19
+ <source srcSet={source.tablet} media={CSS_BREAKPOINTS.tablet} />
20
+ {source.desktopLg ? (
21
+ <>
22
+ <source srcSet={source.desktop} media={CSS_BREAKPOINTS.desktop} />
23
+ <source srcSet={source.desktopLg} />
24
+ </>
25
+ ) : (
26
+ <source srcSet={source.desktop} />
27
+ )}
28
+ <img loading='lazy' src={source.desktop} className={styles.backgroundImage} alt='background' />
29
+ </picture>
30
+ );
31
+ }
@@ -0,0 +1 @@
1
+ export * from './HeroSlideImageBg';
@@ -0,0 +1,20 @@
1
+ .backgroundImageWrapper {
2
+ position: absolute;
3
+ top: 0;
4
+ left: 0;
5
+ width: 100%;
6
+ height: 100%;
7
+ /* stylelint-disable-next-line declaration-property-value-allowed-list */
8
+ z-index: 2;
9
+
10
+ padding: 0;
11
+ display: block;
12
+ line-height: 0;
13
+ }
14
+
15
+ .backgroundImage {
16
+ width: 100%;
17
+ height: 100%;
18
+ object-fit: cover;
19
+ object-position: center 0;
20
+ }
@@ -0,0 +1,22 @@
1
+ import { WithLayoutType } from '@cloud-ru/uikit-product-utils';
2
+
3
+ import { HeroSlideImage } from '../HeroSlideImage';
4
+ import { HeroSlideImageBg } from '../HeroSlideImageBg';
5
+ import { HeroSlideVideoBg } from '../HeroSlideVideoBg';
6
+ import { HeroSlideMediaProps } from './types';
7
+
8
+ export function HeroSlideMedia(props: WithLayoutType<HeroSlideMediaProps>) {
9
+ switch (props.type) {
10
+ case 'image':
11
+ return <HeroSlideImage {...props} />;
12
+
13
+ case 'imageBg':
14
+ return <HeroSlideImageBg {...props} />;
15
+
16
+ case 'videoBg':
17
+ return <HeroSlideVideoBg {...props} />;
18
+
19
+ default:
20
+ return null;
21
+ }
22
+ }
@@ -0,0 +1,2 @@
1
+ export * from './HeroSlideMedia';
2
+ export { type HeroSlideMediaProps } from './types';
@@ -0,0 +1,17 @@
1
+ import { HeroSlideImageProps } from '../HeroSlideImage';
2
+ import { HeroSlideImageBgProps } from '../HeroSlideImageBg';
3
+ import { HeroSlideVideoBgProps } from '../HeroSlideVideoBg';
4
+
5
+ type HeroImageProps = HeroSlideImageProps & {
6
+ type: 'image';
7
+ };
8
+
9
+ type HeroImageBgProps = HeroSlideImageBgProps & {
10
+ type: 'imageBg';
11
+ };
12
+
13
+ type HeroVideoBgProps = HeroSlideVideoBgProps & {
14
+ type: 'videoBg';
15
+ };
16
+
17
+ export type HeroSlideMediaProps = HeroImageProps | HeroImageBgProps | HeroVideoBgProps;
@@ -0,0 +1,36 @@
1
+ import { createRef, RefObject, useEffect } from 'react';
2
+
3
+ type Props = {
4
+ text: string;
5
+ };
6
+
7
+ export function HTMLComment({ text }: Props) {
8
+ const ref: RefObject<HTMLSpanElement> = createRef();
9
+
10
+ useEffect(() => {
11
+ let el: HTMLSpanElement | null = null;
12
+ let parent: ParentNode | null = null;
13
+ let comm: Comment | null = null;
14
+
15
+ if (ref.current) {
16
+ el = ref.current;
17
+ parent = el.parentNode;
18
+ comm = document.createComment(` ${text.trim()} `);
19
+
20
+ try {
21
+ if (parent && parent.contains(el)) {
22
+ parent.replaceChild(comm, el);
23
+ }
24
+ // eslint-disable-next-line
25
+ } catch {}
26
+ }
27
+
28
+ return () => {
29
+ if (parent && el && comm) {
30
+ parent.replaceChild(el, comm);
31
+ }
32
+ };
33
+ }, [ref, text]);
34
+
35
+ return <span ref={ref} style={{ display: 'none' }} />;
36
+ }
@@ -0,0 +1,30 @@
1
+ import { SiteVideo } from '@cloud-ru/uikit-product-site-media';
2
+ import { WithLayoutType } from '@cloud-ru/uikit-product-utils';
3
+
4
+ import { HTMLComment } from './HTMLComment';
5
+
6
+ export type HeroSlideVideoBgProps = {
7
+ /** Ссылка на видео */
8
+ link: string;
9
+ /** Картинка-предпросмотр видео */
10
+ previewImage: string;
11
+ };
12
+
13
+ export function HeroSlideVideoBg({ link, previewImage, layoutType }: WithLayoutType<HeroSlideVideoBgProps>) {
14
+ return (
15
+ <>
16
+ <HTMLComment text='noindex' />
17
+ <SiteVideo
18
+ layoutType={layoutType}
19
+ video={{
20
+ src: link,
21
+ poster: previewImage,
22
+ muted: true,
23
+ loop: true,
24
+ autoPlay: true,
25
+ }}
26
+ />
27
+ <HTMLComment text='/noindex' />
28
+ </>
29
+ );
30
+ }
@@ -0,0 +1 @@
1
+ export * from './HeroSlideVideoBg';
@@ -0,0 +1,5 @@
1
+ export * from './HeroSlide';
2
+ export * from './HeroSlideImage';
3
+ export * from './HeroSlideImageBg';
4
+ export * from './HeroSlideMedia';
5
+ export * from './HeroSlideVideoBg';
@@ -0,0 +1,2 @@
1
+ export * from './HeroSlider';
2
+ export * from './components/HeroSlide/types';
@@ -0,0 +1,41 @@
1
+ @use '@sbercloud/figma-tokens-web/build/scss/styles-theme-variables' as var;
2
+
3
+ $decor: 'decor';
4
+ $graphite: 'graphite';
5
+ $brand: 'brand';
6
+
7
+ .root {
8
+ position: relative;
9
+ touch-action: none;
10
+ }
11
+
12
+ .heroCarousel {
13
+ & > div > div {
14
+ padding: 0;
15
+ margin: 0;
16
+ }
17
+ }
18
+
19
+ .paginationWrapper {
20
+ position: absolute;
21
+ bottom: 24px;
22
+ left: 0;
23
+ right: 0;
24
+
25
+ display: flex;
26
+ justify-content: center;
27
+
28
+ &[data-appearance='#{$brand}'] {
29
+ button[data-activated="true"] > div {
30
+ /* stylelint-disable-next-line declaration-no-important */
31
+ background-color: var.$sys-neutral-accent-default !important;
32
+
33
+ &:hover,
34
+ &:focus-visible,
35
+ &:active {
36
+ /* stylelint-disable-next-line declaration-no-important */
37
+ background-color: var.$sys-neutral-accent-hovered !important;
38
+ }
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,84 @@
1
+ import cn from 'classnames';
2
+
3
+ import { Layout } from '@cloud-ru/uikit-product-site-layout';
4
+ import { RichText } from '@cloud-ru/uikit-product-site-rich-text';
5
+ import { extractSupportProps, WithLayoutType, WithSupportProps } from '@cloud-ru/uikit-product-utils';
6
+ import { Breadcrumbs, Item } from '@snack-uikit/breadcrumbs';
7
+ import { ButtonFilled, ButtonFilledProps } from '@snack-uikit/button';
8
+ import { Typography } from '@snack-uikit/typography';
9
+
10
+ import { HERO_COLORS } from '../../constants';
11
+ import { HeroColor } from '../../types';
12
+ import styles from './styles.module.scss';
13
+ import { getTitleTypographyProps } from './utils';
14
+
15
+ export type HeroZeroProps = WithSupportProps<
16
+ WithLayoutType<{
17
+ /** Хлебные крошки */
18
+ breadcrumbs: Item[];
19
+ /** Название секции */
20
+ title: string;
21
+ /** Описание секции */
22
+ description?: string;
23
+ /** Массив с настройками кнопок ButtonFilled */
24
+ buttons?: [ButtonFilledProps, ButtonFilledProps?];
25
+ /** Наличие нижнего паддинга */
26
+ showBottomPadding?: boolean;
27
+ /** Цвет фона */
28
+ backgroundColor?: HeroColor;
29
+ /** Выравнивание текста */
30
+ contentAlign?: 'left' | 'center';
31
+ /** CSS - класснейм */
32
+ className?: string;
33
+ }>
34
+ >;
35
+
36
+ export function HeroZero({
37
+ breadcrumbs,
38
+ title,
39
+ description,
40
+ layoutType,
41
+ buttons,
42
+ className,
43
+ backgroundColor = HERO_COLORS.NeutralBackground,
44
+ showBottomPadding = true,
45
+ contentAlign = 'left',
46
+ ...rest
47
+ }: HeroZeroProps) {
48
+ return (
49
+ <Layout.SectionWrapper
50
+ layoutType={layoutType}
51
+ className={cn(className, styles.sectionWrapper)}
52
+ data-section-background={backgroundColor}
53
+ {...extractSupportProps(rest)}
54
+ >
55
+ <div className={cn(styles.heroZero, { [styles.withBottomPadding]: showBottomPadding })}>
56
+ <div className={styles.contentLayout} data-layout-type={layoutType}>
57
+ <div className={styles.contentText} data-layout-type={layoutType}>
58
+ <Breadcrumbs items={breadcrumbs} size='xs' />
59
+
60
+ <div className={styles.text} data-layout-type={layoutType} data-align={contentAlign}>
61
+ <Typography family='sans' tag='h1' className={styles.title} {...getTitleTypographyProps(layoutType)}>
62
+ {title}
63
+ </Typography>
64
+
65
+ {description && (
66
+ <Typography.SansBodyL tag='div' className={styles.description}>
67
+ <RichText richText={description} />
68
+ </Typography.SansBodyL>
69
+ )}
70
+ </div>
71
+ </div>
72
+
73
+ {buttons && buttons.length > 0 && (
74
+ <div className={styles.buttons} data-layout-type={layoutType} data-align={contentAlign}>
75
+ {buttons.map((props, index) => (
76
+ <ButtonFilled key={index} className={styles.button} {...props} data-layout-type={layoutType} />
77
+ ))}
78
+ </div>
79
+ )}
80
+ </div>
81
+ </div>
82
+ </Layout.SectionWrapper>
83
+ );
84
+ }
@@ -0,0 +1 @@
1
+ export * from './HeroZero';
@@ -0,0 +1,111 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as var;
2
+
3
+ .heroZero {
4
+ position: relative;
5
+ padding: var.$dimension-5m 0 0;
6
+
7
+ &[data-layout-type='tablet'] {
8
+ padding: var.$dimension-4m 0 0;
9
+ }
10
+
11
+ &[data-layout-type='mobile'] {
12
+ padding: var.$dimension-3m 0 0;
13
+ }
14
+ }
15
+
16
+ .sectionWrapper {
17
+ &[data-section-background='neutral-background1-level'] {
18
+ background-color: var.$sys-neutral-background1-level;
19
+ }
20
+
21
+ &[data-section-background='neutral-background'] {
22
+ background-color: var.$sys-neutral-background;
23
+ }
24
+ }
25
+
26
+ .withBottomPadding {
27
+ padding-bottom: var.$dimension-5m;
28
+
29
+ &[data-layout-type='tablet'] {
30
+ padding-bottom: var.$dimension-4m;
31
+ }
32
+
33
+ &[data-layout-type='mobile'] {
34
+ padding-bottom: var.$dimension-3m;
35
+ }
36
+ }
37
+
38
+ .contentLayout {
39
+ display: flex;
40
+ flex-direction: column;
41
+ gap: var.$dimension-6m;
42
+
43
+ &[data-layout-type='tablet'] {
44
+ gap: var.$dimension-4m;
45
+ }
46
+
47
+ &[data-layout-type='mobile'] {
48
+ gap: var.$dimension-3m;
49
+ }
50
+ }
51
+
52
+ .contentText {
53
+ display: flex;
54
+ flex-direction: column;
55
+ gap: var.$dimension-4m;
56
+
57
+ &[data-layout-type='tablet'],
58
+ &[data-layout-type='mobile']{
59
+ gap: var.$dimension-3m;
60
+ }
61
+ }
62
+
63
+ .text {
64
+ display: flex;
65
+ flex-direction: column;
66
+ gap: calc(#{var.$dimension-1m + var.$dimension-050m});
67
+ max-width: 800px;
68
+ text-align: left;
69
+
70
+ &[data-layout-type='tablet'],
71
+ &[data-layout-type='mobile']{
72
+ gap: var.$dimension-1m;
73
+ max-width: unset;
74
+ }
75
+
76
+ &[data-align='center'] {
77
+ text-align: center;
78
+ align-self: center;
79
+ }
80
+ }
81
+
82
+ .title {
83
+ color: var.$sys-neutral-text-main;
84
+ }
85
+
86
+ .description {
87
+ color: var.$sys-neutral-text-support;
88
+ }
89
+
90
+ .buttons {
91
+ display: flex;
92
+ flex-direction: row;
93
+ gap: var.$dimension-2m;
94
+
95
+ &[data-layout-type='tablet'],
96
+ &[data-layout-type='mobile'] {
97
+ flex-direction: column;
98
+ gap: var.$dimension-1m;
99
+ }
100
+
101
+ &[data-align='center'] {
102
+ justify-content: center;
103
+ }
104
+ }
105
+
106
+ .button{
107
+ &[data-layout-type='tablet'],
108
+ &[data-layout-type='mobile'] {
109
+ width: 100%;
110
+ }
111
+ }
@@ -0,0 +1,15 @@
1
+ import { LayoutType } from '@cloud-ru/uikit-product-utils';
2
+ import { TypographyProps } from '@snack-uikit/typography';
3
+
4
+ export const getTitleTypographyProps = (layoutType: LayoutType): Pick<TypographyProps, 'size' | 'purpose'> => {
5
+ switch (layoutType) {
6
+ case 'tablet':
7
+ case 'mobile':
8
+ return { purpose: 'headline', size: 'l' };
9
+
10
+ case 'desktop':
11
+ case 'desktopSmall':
12
+ default:
13
+ return { purpose: 'display', size: 'm' };
14
+ }
15
+ };
@@ -0,0 +1,4 @@
1
+ export * from './HeroEvent';
2
+ export * from './HeroZero';
3
+ export * from './HeroMain';
4
+ export * from './HeroSlider';
@@ -0,0 +1,12 @@
1
+ export const HERO_EVENT_BUTTONS = {
2
+ Registration: 'registration',
3
+ RegistrationClosed: 'registration-closed',
4
+ Watch: 'watch',
5
+ WatchLater: 'watch-later',
6
+ AdditionalMaterials: 'additional-materials',
7
+ } as const;
8
+
9
+ export const HERO_COLORS = {
10
+ NeutralBackground1Level: 'neutral-background1-level',
11
+ NeutralBackground: 'neutral-background',
12
+ } as const;
@@ -0,0 +1,32 @@
1
+ import { MouseEventHandler } from 'react';
2
+
3
+ import { WithLayoutType } from '@cloud-ru/uikit-product-utils';
4
+ import { ButtonFilled, ButtonFilledProps } from '@snack-uikit/button';
5
+
6
+ import { HERO_BUTTON_META } from './constants';
7
+ import { HeroButtonType } from './types';
8
+
9
+ export type HeroButtonProps = Pick<ButtonFilledProps, 'label' | 'href' | 'disabled' | 'icon'> & {
10
+ type?: HeroButtonType;
11
+ onClick?: MouseEventHandler<HTMLButtonElement>;
12
+ };
13
+
14
+ type HeroButtonPropsInternal = WithLayoutType<HeroButtonProps>;
15
+
16
+ export function HeroEventButton({ href, label, disabled, icon, onClick, type, layoutType }: HeroButtonPropsInternal) {
17
+ const meta = type ? HERO_BUTTON_META[type] : undefined;
18
+ const Icon = meta?.icon;
19
+
20
+ return (
21
+ <ButtonFilled
22
+ size='l'
23
+ onClick={onClick}
24
+ href={href}
25
+ target='_blank'
26
+ disabled={meta?.disabled ?? disabled}
27
+ label={meta?.label ?? label}
28
+ icon={(Icon && <Icon />) ?? icon}
29
+ fullWidth={['mobile', 'tablet'].includes(layoutType)}
30
+ />
31
+ );
32
+ }
@@ -0,0 +1,21 @@
1
+ import { JSXElementConstructor } from 'react';
2
+
3
+ import { DownloadSVG, PlaySVG } from '@cloud-ru/uikit-product-icons';
4
+
5
+ import { HERO_EVENT_BUTTONS } from '../../constants';
6
+ import { HeroButtonType } from './types';
7
+
8
+ export const HERO_BUTTON_META: Record<
9
+ HeroButtonType,
10
+ {
11
+ label: string;
12
+ icon?: JSXElementConstructor<{ size?: number }>;
13
+ disabled?: boolean;
14
+ }
15
+ > = {
16
+ [HERO_EVENT_BUTTONS.Watch]: { label: 'Смотреть запись', icon: PlaySVG },
17
+ [HERO_EVENT_BUTTONS.WatchLater]: { label: 'Запись скоро будет', icon: PlaySVG, disabled: true },
18
+ [HERO_EVENT_BUTTONS.AdditionalMaterials]: { label: 'Получить материал', icon: DownloadSVG },
19
+ [HERO_EVENT_BUTTONS.Registration]: { label: 'Регистрация' },
20
+ [HERO_EVENT_BUTTONS.RegistrationClosed]: { label: 'Регистрация закрыта', disabled: true },
21
+ };
@@ -0,0 +1 @@
1
+ export * from './HeroEventButton';
@@ -0,0 +1,5 @@
1
+ import { ValueOf } from '@snack-uikit/utils';
2
+
3
+ import { HERO_EVENT_BUTTONS } from '../../constants';
4
+
5
+ export type HeroButtonType = ValueOf<typeof HERO_EVENT_BUTTONS>;