@gravity-ui/page-constructor 5.27.0 → 5.27.1-alpha.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.
- package/README.md +54 -0
- package/build/cjs/blocks/HeaderSlider/HeaderSlider.css +0 -10
- package/build/cjs/blocks/HeaderSlider/HeaderSlider.js +2 -2
- package/build/cjs/blocks/Slider/Slider.css +2 -0
- package/build/cjs/blocks/Slider/Slider.d.ts +1 -0
- package/build/cjs/blocks/Slider/Slider.js +85 -31
- package/build/cjs/blocks/Slider/i18n/en.json +3 -1
- package/build/cjs/blocks/Slider/i18n/index.d.ts +1 -1
- package/build/cjs/blocks/Slider/i18n/ru.json +3 -1
- package/build/cjs/blocks/Slider/utils.d.ts +10 -0
- package/build/cjs/blocks/Slider/utils.js +85 -1
- package/build/cjs/blocks/SliderNew/Arrow/Arrow.css +23 -19
- package/build/cjs/blocks/SliderNew/Arrow/Arrow.d.ts +4 -1
- package/build/cjs/blocks/SliderNew/Arrow/Arrow.js +5 -4
- package/build/cjs/blocks/SliderNew/Slider.css +104 -15
- package/build/cjs/blocks/SliderNew/Slider.d.ts +2 -1
- package/build/cjs/blocks/SliderNew/Slider.js +22 -9
- package/build/cjs/blocks/SliderNew/i18n/en.json +3 -1
- package/build/cjs/blocks/SliderNew/i18n/index.d.ts +1 -1
- package/build/cjs/blocks/SliderNew/i18n/ru.json +3 -1
- package/build/cjs/blocks/SliderNew/useSlider.d.ts +8 -6
- package/build/cjs/blocks/SliderNew/useSlider.js +4 -2
- package/build/cjs/blocks/SliderNew/useSliderPagination.d.ts +9 -0
- package/build/cjs/blocks/SliderNew/useSliderPagination.js +36 -0
- package/build/cjs/blocks/SliderNew/utils.d.ts +2 -0
- package/build/cjs/blocks/SliderNew/utils.js +13 -1
- package/build/cjs/components/FullscreenImage/FullscreenImage.css +91 -16
- package/build/cjs/components/FullscreenImage/FullscreenImage.d.ts +5 -0
- package/build/cjs/components/FullscreenImage/FullscreenImage.js +19 -5
- package/build/cjs/components/Media/Image/Image.d.ts +1 -0
- package/build/cjs/components/Media/Image/Image.js +7 -5
- package/build/cjs/components/Media/Media.css +4 -0
- package/build/cjs/components/Media/Media.d.ts +1 -0
- package/build/cjs/components/Media/Media.js +3 -2
- package/build/cjs/components/MediaBase/MediaBase.js +1 -1
- package/build/cjs/components/ReactPlayer/ReactPlayer.js +1 -1
- package/build/cjs/constructor-items.d.ts +1 -1
- package/build/cjs/models/constructor-items/blocks.d.ts +2 -1
- package/build/cjs/models/constructor-items/blocks.js +1 -0
- package/build/cjs/navigation/hooks/useShowBorder.js +3 -2
- package/build/cjs/sub-blocks/Content/Content.css +14 -4
- package/build/cjs/sub-blocks/ImageCard/ImageCard.css +8 -0
- package/build/esm/blocks/HeaderSlider/HeaderSlider.css +0 -10
- package/build/esm/blocks/HeaderSlider/HeaderSlider.js +1 -1
- package/build/esm/blocks/Slider/Slider.css +2 -0
- package/build/esm/blocks/Slider/Slider.d.ts +1 -0
- package/build/esm/blocks/Slider/Slider.js +86 -32
- package/build/esm/blocks/Slider/i18n/en.json +3 -1
- package/build/esm/blocks/Slider/i18n/index.d.ts +1 -1
- package/build/esm/blocks/Slider/i18n/ru.json +3 -1
- package/build/esm/blocks/Slider/utils.d.ts +10 -0
- package/build/esm/blocks/Slider/utils.js +82 -0
- package/build/esm/blocks/SliderNew/Arrow/Arrow.css +23 -19
- package/build/esm/blocks/SliderNew/Arrow/Arrow.d.ts +4 -1
- package/build/esm/blocks/SliderNew/Arrow/Arrow.js +5 -4
- package/build/esm/blocks/SliderNew/Slider.css +104 -15
- package/build/esm/blocks/SliderNew/Slider.d.ts +2 -1
- package/build/esm/blocks/SliderNew/Slider.js +22 -9
- package/build/esm/blocks/SliderNew/i18n/en.json +3 -1
- package/build/esm/blocks/SliderNew/i18n/index.d.ts +1 -1
- package/build/esm/blocks/SliderNew/i18n/ru.json +3 -1
- package/build/esm/blocks/SliderNew/useSlider.d.ts +8 -6
- package/build/esm/blocks/SliderNew/useSlider.js +6 -3
- package/build/esm/blocks/SliderNew/useSliderPagination.d.ts +9 -0
- package/build/esm/blocks/SliderNew/useSliderPagination.js +32 -0
- package/build/esm/blocks/SliderNew/utils.d.ts +2 -0
- package/build/esm/blocks/SliderNew/utils.js +10 -0
- package/build/esm/components/FullscreenImage/FullscreenImage.css +91 -16
- package/build/esm/components/FullscreenImage/FullscreenImage.d.ts +5 -0
- package/build/esm/components/FullscreenImage/FullscreenImage.js +20 -6
- package/build/esm/components/Media/Image/Image.d.ts +1 -0
- package/build/esm/components/Media/Image/Image.js +7 -5
- package/build/esm/components/Media/Media.css +4 -0
- package/build/esm/components/Media/Media.d.ts +1 -0
- package/build/esm/components/Media/Media.js +3 -2
- package/build/esm/components/MediaBase/MediaBase.js +1 -1
- package/build/esm/components/ReactPlayer/ReactPlayer.js +1 -1
- package/build/esm/constructor-items.d.ts +1 -1
- package/build/esm/models/constructor-items/blocks.d.ts +2 -1
- package/build/esm/models/constructor-items/blocks.js +1 -0
- package/build/esm/navigation/hooks/useShowBorder.js +1 -1
- package/build/esm/sub-blocks/Content/Content.css +14 -4
- package/build/esm/sub-blocks/ImageCard/ImageCard.css +8 -0
- package/package.json +2 -1
- package/server/models/constructor-items/blocks.d.ts +2 -1
- package/server/models/constructor-items/blocks.js +1 -0
- package/styles/mixins.scss +1 -1
- package/widget/index.js +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
1
2
|
import pickBy from 'lodash/pickBy';
|
|
2
3
|
import { BREAKPOINTS } from '../../constants';
|
|
3
4
|
import { SliderBreakpointNames } from './models';
|
|
@@ -8,6 +9,37 @@ export const DEFAULT_SLIDE_BREAKPOINTS = {
|
|
|
8
9
|
[SliderBreakpointNames.Sm]: 1.15,
|
|
9
10
|
};
|
|
10
11
|
const BREAKPOINT_NAMES_BY_VALUES = Object.entries(BREAKPOINTS).reduce((acc, [key, value]) => (Object.assign(Object.assign({}, acc), { [value]: key })), {});
|
|
12
|
+
export const isFocusable = (element) => {
|
|
13
|
+
if (!(element instanceof HTMLElement)) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
const tabIndexAttr = element.getAttribute('tabindex');
|
|
17
|
+
const hasTabIndex = tabIndexAttr !== null;
|
|
18
|
+
const tabIndex = Number(tabIndexAttr);
|
|
19
|
+
if (element.ariaHidden === 'true' || (hasTabIndex && tabIndex < 0)) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if (hasTabIndex && tabIndex >= 0) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
// without this jest fails here for some reason
|
|
26
|
+
let htmlElement;
|
|
27
|
+
switch (true) {
|
|
28
|
+
case element instanceof HTMLAnchorElement:
|
|
29
|
+
htmlElement = element;
|
|
30
|
+
return Boolean(htmlElement.href);
|
|
31
|
+
case element instanceof HTMLInputElement:
|
|
32
|
+
htmlElement = element;
|
|
33
|
+
return htmlElement.type !== 'hidden' && !htmlElement.disabled;
|
|
34
|
+
case element instanceof HTMLSelectElement:
|
|
35
|
+
case element instanceof HTMLTextAreaElement:
|
|
36
|
+
case element instanceof HTMLButtonElement:
|
|
37
|
+
htmlElement = element;
|
|
38
|
+
return !htmlElement.disabled;
|
|
39
|
+
default:
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
11
43
|
export function getSlidesToShowWithDefaults({ contentLength, breakpoints, mobileFullscreen, }) {
|
|
12
44
|
let result;
|
|
13
45
|
if (typeof breakpoints === 'number') {
|
|
@@ -31,3 +63,53 @@ export function getSlidesCountByBreakpoint(breakpoint, breakpoints) {
|
|
|
31
63
|
export function getSlidesToShowCount(breakpoints) {
|
|
32
64
|
return Math.floor(Math.max(...Object.values(breakpoints)));
|
|
33
65
|
}
|
|
66
|
+
const getRovingListItemId = (uniqId, index) => `${uniqId}-roving-tabindex-item-${index}`;
|
|
67
|
+
export function useRovingTabIndex(props) {
|
|
68
|
+
const { itemCount, activeIndex, firstIndex = 0, uniqId } = props;
|
|
69
|
+
const [currentIndex, setCurrentIndex] = useState(firstIndex);
|
|
70
|
+
const hasFocusRef = useRef(false);
|
|
71
|
+
const lastIndex = itemCount + firstIndex - 1;
|
|
72
|
+
const getRovingItemProps = (index) => {
|
|
73
|
+
return {
|
|
74
|
+
id: getRovingListItemId(uniqId, index),
|
|
75
|
+
tabIndex: index === activeIndex ? 0 : -1,
|
|
76
|
+
onFocus: () => {
|
|
77
|
+
setCurrentIndex(index);
|
|
78
|
+
hasFocusRef.current = true;
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
var _a;
|
|
84
|
+
if (!hasFocusRef.current) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
(_a = document.getElementById(getRovingListItemId(uniqId, currentIndex))) === null || _a === void 0 ? void 0 : _a.focus();
|
|
88
|
+
}, [activeIndex, currentIndex, uniqId]);
|
|
89
|
+
const setNextIndex = () => setCurrentIndex((prev) => (prev >= lastIndex ? firstIndex : prev + 1));
|
|
90
|
+
const setPrevIndex = () => setCurrentIndex((prev) => (prev <= firstIndex ? lastIndex : prev - 1));
|
|
91
|
+
const onRovingListKeyDown = (e) => {
|
|
92
|
+
const key = e.key.toLowerCase();
|
|
93
|
+
if (key !== 'tab' && key !== 'enter') {
|
|
94
|
+
e.preventDefault();
|
|
95
|
+
}
|
|
96
|
+
switch (key) {
|
|
97
|
+
case 'arrowleft':
|
|
98
|
+
case 'arrowup':
|
|
99
|
+
setPrevIndex();
|
|
100
|
+
return;
|
|
101
|
+
case 'arrowright':
|
|
102
|
+
case 'arrowdown':
|
|
103
|
+
setNextIndex();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const onRovingListBlur = () => {
|
|
108
|
+
hasFocusRef.current = false;
|
|
109
|
+
};
|
|
110
|
+
const rovingListProps = {
|
|
111
|
+
onKeyDown: onRovingListKeyDown,
|
|
112
|
+
onBlur: onRovingListBlur,
|
|
113
|
+
};
|
|
114
|
+
return { getRovingItemProps, rovingListProps };
|
|
115
|
+
}
|
|
@@ -1,33 +1,25 @@
|
|
|
1
|
-
.pc-slider-new-block-
|
|
1
|
+
.pc-slider-new-block-arrow__inner {
|
|
2
2
|
box-shadow: 0px 4px 24px var(--pc-color-sfx-shadow), 0px 2px 8px var(--pc-color-sfx-shadow);
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
-
.pc-slider-new-block-
|
|
5
|
+
.pc-slider-new-block-arrow__inner:hover {
|
|
6
6
|
box-shadow: 0px 4px 24px var(--g-color-sfx-shadow), 0px 2px 8px var(--g-color-sfx-shadow);
|
|
7
7
|
cursor: pointer;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
/* use this for style redefinitions to awoid problems with
|
|
11
11
|
unpredictable css rules order in build */
|
|
12
|
-
.pc-slider-new-block-arrow__icon-wrapper, .pc-slider-new-block-
|
|
12
|
+
.pc-slider-new-block-arrow__icon-wrapper, .pc-slider-new-block-arrow__inner, .pc-slider-new-block-arrow {
|
|
13
13
|
display: flex;
|
|
14
14
|
align-items: center;
|
|
15
15
|
justify-content: center;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
.pc-slider-new-block-arrow {
|
|
19
|
-
width: 42px;
|
|
20
|
-
height: 42px;
|
|
21
|
-
cursor: pointer;
|
|
22
|
-
}
|
|
23
18
|
@media (max-width: 576px) {
|
|
24
19
|
.pc-slider-new-block-arrow {
|
|
25
20
|
display: none;
|
|
26
21
|
}
|
|
27
22
|
}
|
|
28
|
-
.pc-slider-new-block-arrow_type_left .pc-slider-new-block-arrow__icon-wrapper {
|
|
29
|
-
transform: rotate(180deg);
|
|
30
|
-
}
|
|
31
23
|
.pc-slider-new-block-arrow__button {
|
|
32
24
|
display: inline-block;
|
|
33
25
|
margin: 0;
|
|
@@ -38,13 +30,6 @@ unpredictable css rules order in build */
|
|
|
38
30
|
color: inherit;
|
|
39
31
|
background: none;
|
|
40
32
|
cursor: pointer;
|
|
41
|
-
width: 42px;
|
|
42
|
-
height: 42px;
|
|
43
|
-
color: var(--g-color-text-secondary);
|
|
44
|
-
border-radius: 100%;
|
|
45
|
-
background-color: var(--g-color-base-background);
|
|
46
|
-
box-shadow: 0 4px 24px var(--pc-color-sfx-shadow), 0 2px 8px var(--pc-color-sfx-shadow);
|
|
47
|
-
transition: box-shadow 0.3s cubic-bezier(0.22, 0.61, 0.36, 1), color 0.3s cubic-bezier(0.22, 0.61, 0.36, 1);
|
|
48
33
|
}
|
|
49
34
|
.pc-slider-new-block-arrow__button:focus {
|
|
50
35
|
outline: 2px solid var(--g-color-line-focus);
|
|
@@ -53,10 +38,29 @@ unpredictable css rules order in build */
|
|
|
53
38
|
.pc-slider-new-block-arrow__button:focus:not(:focus-visible) {
|
|
54
39
|
outline: 0;
|
|
55
40
|
}
|
|
56
|
-
.pc-slider-new-block-
|
|
41
|
+
.pc-slider-new-block-arrow__inner {
|
|
42
|
+
width: 42px;
|
|
43
|
+
height: 42px;
|
|
44
|
+
color: var(--g-color-text-secondary);
|
|
45
|
+
border-radius: 100%;
|
|
46
|
+
background-color: var(--g-color-base-background);
|
|
47
|
+
box-shadow: 0 4px 24px var(--pc-color-sfx-shadow), 0 2px 8px var(--pc-color-sfx-shadow);
|
|
48
|
+
transition: box-shadow 0.3s cubic-bezier(0.22, 0.61, 0.36, 1), color 1s cubic-bezier(0.22, 0.61, 0.36, 1);
|
|
49
|
+
}
|
|
50
|
+
.pc-slider-new-block-arrow__inner_type_left .pc-slider-new-block-arrow__icon-wrapper {
|
|
51
|
+
transform: rotate(180deg);
|
|
52
|
+
}
|
|
53
|
+
.pc-slider-new-block-arrow__inner:hover {
|
|
57
54
|
color: var(--g-color-text-primary);
|
|
58
55
|
box-shadow: 0 2px 12px var(--pc-color-sfx-shadow), 0 4px 24px var(--pc-color-sfx-shadow);
|
|
59
56
|
}
|
|
57
|
+
.pc-slider-new-block-arrow__inner_transparent {
|
|
58
|
+
background-color: transparent;
|
|
59
|
+
box-shadow: none;
|
|
60
|
+
}
|
|
61
|
+
.pc-slider-new-block-arrow__inner_transparent:hover {
|
|
62
|
+
box-shadow: none;
|
|
63
|
+
}
|
|
60
64
|
.pc-slider-new-block-arrow__icon {
|
|
61
65
|
position: relative;
|
|
62
66
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
import { ClassNameProps } from '../../../models';
|
|
2
3
|
import './Arrow.css';
|
|
3
4
|
export type ArrowType = 'left' | 'right';
|
|
4
5
|
export interface ArrowProps {
|
|
5
6
|
type: ArrowType;
|
|
7
|
+
transparent?: boolean;
|
|
6
8
|
onClick?: () => void;
|
|
7
9
|
size?: number;
|
|
10
|
+
extraProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
8
11
|
}
|
|
9
|
-
declare const Arrow: ({ type, onClick, className, size }: ArrowProps & ClassNameProps) => JSX.Element;
|
|
12
|
+
declare const Arrow: ({ type, transparent, onClick, className, size, extraProps, }: ArrowProps & ClassNameProps) => JSX.Element;
|
|
10
13
|
export default Arrow;
|
|
@@ -4,8 +4,9 @@ import { block } from '../../../utils';
|
|
|
4
4
|
import { i18n } from '../i18n';
|
|
5
5
|
import './Arrow.css';
|
|
6
6
|
const b = block('slider-new-block-arrow');
|
|
7
|
-
const Arrow = ({ type, onClick, className, size = 16 }) => (React.createElement("div", { className: b(
|
|
8
|
-
React.createElement("button", { className: b('button'), onClick: onClick, "aria-label": i18n(`arrow-${type}`) },
|
|
9
|
-
React.createElement("
|
|
10
|
-
React.createElement(
|
|
7
|
+
const Arrow = ({ type, transparent, onClick, className, size = 16, extraProps, }) => (React.createElement("div", { className: b(null, className) },
|
|
8
|
+
React.createElement("button", Object.assign({ className: b('button'), onClick: onClick, "aria-label": i18n(`arrow-${type}`) }, extraProps),
|
|
9
|
+
React.createElement("div", { className: b('inner', { type, transparent }) },
|
|
10
|
+
React.createElement("span", { className: b('icon-wrapper') },
|
|
11
|
+
React.createElement(ToggleArrow, { size: size, type: 'horizontal', iconType: "navigation", className: b('icon') }))))));
|
|
11
12
|
export default Arrow;
|
|
@@ -27,6 +27,14 @@ unpredictable css rules order in build */
|
|
|
27
27
|
.pc-SliderNewBlock__slide.swiper-slide.swiper-slide-visible {
|
|
28
28
|
animation: safari-fix 300ms;
|
|
29
29
|
}
|
|
30
|
+
.pc-SliderNewBlock__slide.swiper-slide .pc-SliderNewBlock__slide-item {
|
|
31
|
+
width: 100%;
|
|
32
|
+
height: 100%;
|
|
33
|
+
}
|
|
34
|
+
.pc-SliderNewBlock .pc-SliderNewBlock__slide-item {
|
|
35
|
+
width: 100%;
|
|
36
|
+
height: 100%;
|
|
37
|
+
}
|
|
30
38
|
.pc-SliderNewBlock__arrow {
|
|
31
39
|
position: absolute;
|
|
32
40
|
top: -2px;
|
|
@@ -48,6 +56,7 @@ unpredictable css rules order in build */
|
|
|
48
56
|
background-color: var(--g-color-line-generic-accent);
|
|
49
57
|
cursor: pointer;
|
|
50
58
|
display: inline-block;
|
|
59
|
+
transition: background-color 1s;
|
|
51
60
|
}
|
|
52
61
|
.pc-SliderNewBlock__dot:hover {
|
|
53
62
|
background-color: var(--g-color-line-generic-accent-hover);
|
|
@@ -712,7 +721,7 @@ unpredictable css rules order in build */
|
|
|
712
721
|
padding: 0;
|
|
713
722
|
}
|
|
714
723
|
@media (max-width: 577px) {
|
|
715
|
-
.pc-SliderNewBlock_type_media-card:not(.pc-
|
|
724
|
+
.pc-SliderNewBlock_type_media-card.pc-SliderNewBlock:not(.pc-SliderNewBlock_one-slide) {
|
|
716
725
|
margin-left: 0;
|
|
717
726
|
padding-left: 0;
|
|
718
727
|
width: 100%;
|
|
@@ -747,7 +756,7 @@ unpredictable css rules order in build */
|
|
|
747
756
|
padding-top: 0;
|
|
748
757
|
}
|
|
749
758
|
@media (max-width: 577px) {
|
|
750
|
-
.pc-SliderNewBlock_type_header-card:not(.pc-
|
|
759
|
+
.pc-SliderNewBlock_type_header-card.pc-SliderNewBlock:not(.pc-SliderNewBlock_one-slide) {
|
|
751
760
|
margin-left: 0;
|
|
752
761
|
padding-left: 0;
|
|
753
762
|
width: 100%;
|
|
@@ -775,32 +784,109 @@ unpredictable css rules order in build */
|
|
|
775
784
|
left: 0;
|
|
776
785
|
margin-right: 0;
|
|
777
786
|
}
|
|
778
|
-
.pc-SliderNewBlock_type_header-card .pc-
|
|
779
|
-
|
|
780
|
-
|
|
787
|
+
.pc-SliderNewBlock_type_header-card:has(.swiper-slide-active .pc-header-block_controls-view_light) .pc-slider-new-block-arrow__inner {
|
|
788
|
+
color: var(--g-color-text-dark-primary);
|
|
789
|
+
}
|
|
790
|
+
.pc-SliderNewBlock_type_header-card:has(.swiper-slide-active .pc-header-block_controls-view_light) .pc-SliderNewBlock__dot {
|
|
791
|
+
background-color: var(--g-color-private-black-150);
|
|
792
|
+
}
|
|
793
|
+
.pc-SliderNewBlock_type_header-card:has(.swiper-slide-active .pc-header-block_controls-view_light) .pc-SliderNewBlock__dot_active {
|
|
794
|
+
background-color: var(--g-color-private-black-300);
|
|
781
795
|
}
|
|
782
|
-
.pc-SliderNewBlock_type_header-card .pc-
|
|
783
|
-
|
|
796
|
+
.pc-SliderNewBlock_type_header-card:has(.swiper-slide-active .pc-header-block_controls-view_dark) .pc-slider-new-block-arrow__inner {
|
|
797
|
+
color: var(--g-color-text-light-primary);
|
|
784
798
|
}
|
|
785
|
-
.pc-SliderNewBlock_type_header-card .pc-
|
|
786
|
-
|
|
799
|
+
.pc-SliderNewBlock_type_header-card:has(.swiper-slide-active .pc-header-block_controls-view_dark) .pc-SliderNewBlock__dot {
|
|
800
|
+
background-color: var(--g-color-private-white-150);
|
|
801
|
+
}
|
|
802
|
+
.pc-SliderNewBlock_type_header-card:has(.swiper-slide-active .pc-header-block_controls-view_dark) .pc-SliderNewBlock__dot_active {
|
|
803
|
+
background-color: var(--g-color-private-white-300);
|
|
787
804
|
}
|
|
788
805
|
.pc-SliderNewBlock_type_header-card .pc-SliderNewBlock__slide {
|
|
789
806
|
padding: 0;
|
|
790
807
|
}
|
|
808
|
+
@media (max-width: 769px) {
|
|
809
|
+
.pc-SliderNewBlock_type_header-card.pc-SliderNewBlock:not(.pc-SliderNewBlock_one-slide) {
|
|
810
|
+
margin-left: -8px;
|
|
811
|
+
padding-left: 0;
|
|
812
|
+
width: calc(100% + 8px);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
791
815
|
@media (max-width: 577px) {
|
|
792
816
|
.pc-SliderNewBlock_type_header-card .pc-SliderNewBlock__arrow {
|
|
793
817
|
display: none;
|
|
794
818
|
}
|
|
795
|
-
.pc-SliderNewBlock_type_header-card.pc-SliderNewBlock:not(.pc-
|
|
819
|
+
.pc-SliderNewBlock_type_header-card.pc-SliderNewBlock:not(.pc-SliderNewBlock_one-slide) .pc-SliderNewBlock__slider {
|
|
796
820
|
margin-left: 0;
|
|
797
821
|
}
|
|
798
|
-
.pc-SliderNewBlock_type_header-card.pc-SliderNewBlock:not(.pc-
|
|
799
|
-
padding-right: 0;
|
|
822
|
+
.pc-SliderNewBlock_type_header-card.pc-SliderNewBlock:not(.pc-SliderNewBlock_one-slide) .swiper-wrapper {
|
|
800
823
|
padding-left: 0;
|
|
801
824
|
}
|
|
802
|
-
.pc-SliderNewBlock_type_header-card.pc-SliderNewBlock:not(.pc-
|
|
825
|
+
.pc-SliderNewBlock_type_header-card.pc-SliderNewBlock:not(.pc-SliderNewBlock_one-slide) .pc-SliderNewBlock__slide {
|
|
803
826
|
padding-right: 0;
|
|
827
|
+
padding-left: 0;
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
.pc-SliderNewBlock_type_fullscreen-card {
|
|
831
|
+
padding-top: 0;
|
|
832
|
+
}
|
|
833
|
+
@media (max-width: 577px) {
|
|
834
|
+
.pc-SliderNewBlock_type_fullscreen-card.pc-SliderNewBlock:not(.pc-SliderNewBlock_one-slide) {
|
|
835
|
+
margin-left: 0;
|
|
836
|
+
padding-left: 0;
|
|
837
|
+
width: 100%;
|
|
838
|
+
overflow: inherit;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
.pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock__slider {
|
|
842
|
+
padding: 24px 0 40px;
|
|
843
|
+
height: 100vh;
|
|
844
|
+
margin: 0;
|
|
845
|
+
}
|
|
846
|
+
.pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock__slider .swiper-pagination {
|
|
847
|
+
bottom: 11px;
|
|
848
|
+
}
|
|
849
|
+
.pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock__slider .pc-SliderNewBlock__dot {
|
|
850
|
+
background-color: var(--g-color-text-light-hint);
|
|
851
|
+
}
|
|
852
|
+
.pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock__slider .pc-SliderNewBlock__dot_active {
|
|
853
|
+
background-color: var(--g-color-text-light-primary);
|
|
854
|
+
}
|
|
855
|
+
.pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock__slider .pc-SliderNewBlock__slide {
|
|
856
|
+
height: 100%;
|
|
857
|
+
padding: 0 120px;
|
|
858
|
+
}
|
|
859
|
+
.pc-SliderNewBlock_type_fullscreen-card:hover .pc-SliderNewBlock__arrow {
|
|
860
|
+
display: flex;
|
|
861
|
+
}
|
|
862
|
+
.pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock__arrow {
|
|
863
|
+
display: none;
|
|
864
|
+
width: 120px;
|
|
865
|
+
top: 40px;
|
|
866
|
+
bottom: 40px;
|
|
867
|
+
}
|
|
868
|
+
.pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock__arrow_prev {
|
|
869
|
+
left: 0;
|
|
870
|
+
margin-right: 0;
|
|
871
|
+
}
|
|
872
|
+
@media (max-width: 769px) {
|
|
873
|
+
.pc-SliderNewBlock_type_fullscreen-card {
|
|
874
|
+
margin-left: 0;
|
|
875
|
+
}
|
|
876
|
+
.pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock_slider {
|
|
877
|
+
margin-left: 0;
|
|
878
|
+
width: 100%;
|
|
879
|
+
}
|
|
880
|
+
.pc-SliderNewBlock_type_fullscreen-card:hover .pc-SliderNewBlock__arrow {
|
|
881
|
+
display: none;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
@media (max-width: 577px) {
|
|
885
|
+
.pc-SliderNewBlock_type_fullscreen-card:not(.pc-SliderNewBlock_one-slide) .pc-SliderNewBlock__slider {
|
|
886
|
+
margin-left: 0;
|
|
887
|
+
}
|
|
888
|
+
.pc-SliderNewBlock_type_fullscreen-card:not(.pc-SliderNewBlock_one-slide) .swiper-wrapper {
|
|
889
|
+
padding-left: 0;
|
|
804
890
|
}
|
|
805
891
|
}
|
|
806
892
|
@media (max-width: 769px) {
|
|
@@ -821,8 +907,11 @@ unpredictable css rules order in build */
|
|
|
821
907
|
overflow-x: auto;
|
|
822
908
|
}
|
|
823
909
|
.pc-SliderNewBlock:not(.pc-SliderNewBlock_one-slide) .pc-SliderNewBlock__slider {
|
|
824
|
-
|
|
825
|
-
margin: 0
|
|
910
|
+
margin-left: -24px;
|
|
911
|
+
margin-right: 0;
|
|
912
|
+
}
|
|
913
|
+
.pc-SliderNewBlock:not(.pc-SliderNewBlock_one-slide) .swiper-wrapper {
|
|
914
|
+
padding-left: 16px;
|
|
826
915
|
}
|
|
827
916
|
.pc-SliderNewBlock:not(.pc-SliderNewBlock_one-slide) .pc-SliderNewBlock__slide {
|
|
828
917
|
padding: 0 8px;
|
|
@@ -9,6 +9,7 @@ export interface SliderNewProps extends Omit<SliderParams, 'children'>, Partial<
|
|
|
9
9
|
dotsClassName?: string;
|
|
10
10
|
blockClassName?: string;
|
|
11
11
|
arrowSize?: number;
|
|
12
|
+
initialSlide?: number;
|
|
12
13
|
}
|
|
13
|
-
export declare const SliderNewBlock: ({ animated, title, description, type, anchorId, arrows, adaptive, autoplay: autoplayMs, dots, className, dotsClassName, disclaimer, children, blockClassName, arrowSize, slidesToShow, onSlideChange, onSlideChangeTransitionStart, onSlideChangeTransitionEnd, onActiveIndexChange, onBreakpoint, }: PropsWithChildren<SliderNewProps>) => JSX.Element;
|
|
14
|
+
export declare const SliderNewBlock: ({ animated, title, description, type, anchorId, arrows, adaptive, autoplay: autoplayMs, dots, initialSlide, className, dotsClassName, disclaimer, children, blockClassName, arrowSize, slidesToShow, onSlideChange, onSlideChangeTransitionStart, onSlideChangeTransitionEnd, onActiveIndexChange, onBreakpoint, }: PropsWithChildren<SliderNewProps>) => JSX.Element;
|
|
14
15
|
export default SliderNewBlock;
|
|
@@ -4,20 +4,33 @@ import { Swiper, SwiperSlide } from 'swiper/react';
|
|
|
4
4
|
import Anchor from '../../components/Anchor/Anchor';
|
|
5
5
|
import AnimateBlock from '../../components/AnimateBlock/AnimateBlock';
|
|
6
6
|
import Title from '../../components/Title/Title';
|
|
7
|
+
import { SliderType } from '../../models';
|
|
7
8
|
import { block } from '../../utils';
|
|
8
9
|
import Arrow from './Arrow/Arrow';
|
|
10
|
+
import { i18n } from './i18n';
|
|
9
11
|
import { useSlider } from './useSlider';
|
|
12
|
+
import { useSliderPagination } from './useSliderPagination';
|
|
10
13
|
import './Slider.css';
|
|
11
14
|
import 'swiper/swiper-bundle.css';
|
|
12
15
|
const b = block('SliderNewBlock');
|
|
13
16
|
SwiperCore.use([Autoplay, A11y, Pagination]);
|
|
14
|
-
export const SliderNewBlock = ({ animated, title, description, type, anchorId, arrows = true, adaptive, autoplay: autoplayMs, dots = true, className, dotsClassName, disclaimer, children, blockClassName, arrowSize, slidesToShow, onSlideChange, onSlideChangeTransitionStart, onSlideChangeTransitionEnd, onActiveIndexChange, onBreakpoint, }) => {
|
|
15
|
-
const { childrenCount, breakpoints,
|
|
17
|
+
export const SliderNewBlock = ({ animated, title, description, type, anchorId, arrows = true, adaptive, autoplay: autoplayMs, dots = true, initialSlide = 0, className, dotsClassName, disclaimer, children, blockClassName, arrowSize, slidesToShow, onSlideChange, onSlideChangeTransitionStart, onSlideChangeTransitionEnd, onActiveIndexChange, onBreakpoint, }) => {
|
|
18
|
+
const { autoplay, isLocked, childrenCount, breakpoints, onSwiper, onPrev, onNext, setIsLocked } = useSlider({
|
|
16
19
|
slidesToShow,
|
|
17
20
|
children,
|
|
18
21
|
type,
|
|
19
22
|
autoplayMs,
|
|
20
23
|
});
|
|
24
|
+
const isA11yControlHidden = Boolean(autoplay);
|
|
25
|
+
const controlTabIndex = isA11yControlHidden ? -1 : 0;
|
|
26
|
+
const paginationProps = useSliderPagination({
|
|
27
|
+
enabled: dots,
|
|
28
|
+
isA11yControlHidden,
|
|
29
|
+
controlTabIndex,
|
|
30
|
+
bulletClass: b('dot', dotsClassName),
|
|
31
|
+
bulletActiveClass: b('dot_active'),
|
|
32
|
+
paginationLabel: i18n('pagination-label'),
|
|
33
|
+
});
|
|
21
34
|
return (React.createElement("div", { className: b({
|
|
22
35
|
'one-slide': childrenCount === 1,
|
|
23
36
|
'only-arrows': !(title === null || title === void 0 ? void 0 : title.text) && !description && arrows,
|
|
@@ -27,14 +40,14 @@ export const SliderNewBlock = ({ animated, title, description, type, anchorId, a
|
|
|
27
40
|
anchorId && React.createElement(Anchor, { id: anchorId }),
|
|
28
41
|
React.createElement(Title, { title: title, subtitle: description, className: b('header', { 'no-description': !description }) }),
|
|
29
42
|
React.createElement(AnimateBlock, { className: b('animate-slides'), animate: animated },
|
|
30
|
-
React.createElement(Swiper, { className: b('slider', className), onSwiper: onSwiper,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}, speed: 1000, autoplay: autoplay, autoHeight: adaptive, initialSlide: 0, noSwiping: false, breakpoints: breakpoints, onSlideChange: onSlideChange, onSlideChangeTransitionStart: onSlideChangeTransitionStart, onSlideChangeTransitionEnd: onSlideChangeTransitionEnd, onActiveIndexChange: onActiveIndexChange, onBreakpoint: onBreakpoint, onLock: () => setIsLocked(true), onUnlock: () => setIsLocked(false), watchSlidesVisibility: true, watchOverflow: true }, React.Children.map(children, (elem, index) => (React.createElement(SwiperSlide, { className: b('slide'), key: index }, elem)))),
|
|
43
|
+
React.createElement(Swiper, Object.assign({ className: b('slider', className), onSwiper: onSwiper, speed: 1000, autoplay: autoplay, autoHeight: adaptive, initialSlide: initialSlide, noSwiping: false, breakpoints: breakpoints, onSlideChange: onSlideChange, onSlideChangeTransitionStart: onSlideChangeTransitionStart, onSlideChangeTransitionEnd: onSlideChangeTransitionEnd, onActiveIndexChange: onActiveIndexChange, onBreakpoint: onBreakpoint, onLock: () => setIsLocked(true), onUnlock: () => setIsLocked(false), watchSlidesVisibility: true, watchOverflow: true, a11y: {
|
|
44
|
+
slideLabelMessage: '',
|
|
45
|
+
paginationBulletMessage: i18n('dot-label', { index: '{{index}}' }),
|
|
46
|
+
} }, paginationProps), React.Children.map(children, (elem, index) => (React.createElement(SwiperSlide, { className: b('slide'), key: index }, ({ isVisible }) => (React.createElement("div", { className: b('slide-item'), "aria-hidden": !isA11yControlHidden && !isVisible }, elem)))))),
|
|
35
47
|
arrows && !isLocked && (React.createElement(Fragment, null,
|
|
36
|
-
React.createElement(
|
|
37
|
-
|
|
48
|
+
React.createElement("div", { "aria-hidden": isA11yControlHidden },
|
|
49
|
+
React.createElement(Arrow, { className: b('arrow', { prev: true }), type: "left", transparent: type === SliderType.HeaderCard, onClick: onPrev, size: arrowSize, extraProps: { tabIndex: controlTabIndex } }),
|
|
50
|
+
React.createElement(Arrow, { className: b('arrow', { next: true }), type: "right", transparent: type === SliderType.HeaderCard, onClick: onNext, size: arrowSize, extraProps: { tabIndex: controlTabIndex } })))),
|
|
38
51
|
React.createElement("div", { className: b('footer') }, disclaimer ? (React.createElement("div", { className: b('disclaimer', { size: (disclaimer === null || disclaimer === void 0 ? void 0 : disclaimer.size) || 'm' }) }, disclaimer === null || disclaimer === void 0 ? void 0 : disclaimer.text)) : null))));
|
|
39
52
|
};
|
|
40
53
|
export default SliderNewBlock;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const i18n: (key: "arrow-right" | "arrow-left", params?: import("@gravity-ui/i18n").Params | undefined) => string;
|
|
1
|
+
export declare const i18n: (key: "arrow-right" | "arrow-left" | "dot-label" | "pagination-label", params?: import("@gravity-ui/i18n").Params | undefined) => string;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from 'react';
|
|
2
2
|
import type { Swiper } from 'swiper';
|
|
3
3
|
import { SlidesToShow } from '../../models';
|
|
4
|
-
|
|
5
|
-
autoplayMs?: number
|
|
6
|
-
type?: string
|
|
7
|
-
slidesToShow?: SlidesToShow
|
|
8
|
-
}
|
|
4
|
+
type UseSliderProps = PropsWithChildren<{
|
|
5
|
+
autoplayMs?: number;
|
|
6
|
+
type?: string;
|
|
7
|
+
slidesToShow?: SlidesToShow;
|
|
8
|
+
}>;
|
|
9
|
+
export declare const useSlider: ({ children, autoplayMs, type, ...props }: UseSliderProps) => {
|
|
9
10
|
slider: Swiper | undefined;
|
|
10
11
|
onSwiper: React.Dispatch<React.SetStateAction<Swiper | undefined>>;
|
|
11
12
|
onNext: () => void;
|
|
@@ -15,7 +16,8 @@ export declare const useSlider: ({ children, autoplayMs, type, slidesToShow, }:
|
|
|
15
16
|
isLocked: boolean;
|
|
16
17
|
setIsLocked: React.Dispatch<React.SetStateAction<boolean>>;
|
|
17
18
|
autoplay: false | {
|
|
18
|
-
delay: number
|
|
19
|
+
delay: number;
|
|
19
20
|
disableOnInteraction: boolean;
|
|
20
21
|
};
|
|
21
22
|
};
|
|
23
|
+
export {};
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { __rest } from "tslib";
|
|
1
2
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
3
|
import { SliderType } from '../../models';
|
|
3
|
-
import { getSliderResponsiveParams } from './utils';
|
|
4
|
-
export const useSlider = (
|
|
4
|
+
import { getSliderResponsiveParams, useMemoized } from './utils';
|
|
5
|
+
export const useSlider = (_a) => {
|
|
6
|
+
var { children, autoplayMs, type } = _a, props = __rest(_a, ["children", "autoplayMs", "type"]);
|
|
5
7
|
const [slider, setSlider] = useState();
|
|
6
8
|
const [isLocked, setIsLocked] = useState(false);
|
|
9
|
+
const slidesToShow = useMemoized(props.slidesToShow);
|
|
7
10
|
const childrenCount = React.Children.count(children);
|
|
8
|
-
const autoplayEnabled =
|
|
11
|
+
const autoplayEnabled = autoplayMs !== undefined && autoplayMs > 0;
|
|
9
12
|
const breakpoints = useMemo(() => {
|
|
10
13
|
return getSliderResponsiveParams({
|
|
11
14
|
contentLength: childrenCount,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Swiper as SwiperProps } from 'swiper/swiper-react';
|
|
2
|
+
export declare const useSliderPagination: (props: {
|
|
3
|
+
enabled: boolean;
|
|
4
|
+
isA11yControlHidden: boolean;
|
|
5
|
+
controlTabIndex: number;
|
|
6
|
+
bulletClass: string;
|
|
7
|
+
bulletActiveClass: string;
|
|
8
|
+
paginationLabel: string;
|
|
9
|
+
}) => Pick<SwiperProps, 'pagination' | 'onPaginationUpdate'> | undefined;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { setElementAtrributes } from './utils';
|
|
2
|
+
export const useSliderPagination = (props) => {
|
|
3
|
+
if (!props.enabled) {
|
|
4
|
+
return undefined;
|
|
5
|
+
}
|
|
6
|
+
const { isA11yControlHidden, controlTabIndex, bulletClass, bulletActiveClass, paginationLabel } = props;
|
|
7
|
+
return {
|
|
8
|
+
pagination: {
|
|
9
|
+
clickable: true,
|
|
10
|
+
bulletClass,
|
|
11
|
+
bulletActiveClass,
|
|
12
|
+
},
|
|
13
|
+
onPaginationUpdate: (slider) => {
|
|
14
|
+
const pagination = slider.pagination.el;
|
|
15
|
+
setElementAtrributes(pagination, {
|
|
16
|
+
role: 'menu',
|
|
17
|
+
'aria-hidden': isA11yControlHidden,
|
|
18
|
+
'aria-label': paginationLabel,
|
|
19
|
+
});
|
|
20
|
+
const bullets = pagination.querySelectorAll(`.${bulletClass}`);
|
|
21
|
+
bullets.forEach((bullet) => {
|
|
22
|
+
const isActive = bullet.classList.contains(bulletActiveClass);
|
|
23
|
+
setElementAtrributes(bullet, {
|
|
24
|
+
role: 'menuitemradio',
|
|
25
|
+
'aria-hidden': isA11yControlHidden,
|
|
26
|
+
'aria-checked': isActive,
|
|
27
|
+
tabindex: controlTabIndex,
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
};
|
|
@@ -12,3 +12,5 @@ export interface GetSlidesToShowParams {
|
|
|
12
12
|
mobileFullscreen?: boolean;
|
|
13
13
|
}
|
|
14
14
|
export declare function getSliderResponsiveParams({ contentLength, slidesToShow, mobileFullscreen, }: GetSlidesToShowParams): Record<number, SwiperOptions>;
|
|
15
|
+
export declare const useMemoized: <T>(value: T) => T;
|
|
16
|
+
export declare const setElementAtrributes: (element: Element, attributes: Record<string, unknown>) => void;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import isEqual from 'lodash/isEqual';
|
|
1
3
|
import pickBy from 'lodash/pickBy';
|
|
2
4
|
import { BREAKPOINTS } from '../../constants';
|
|
3
5
|
import { SliderBreakpointNames } from './models';
|
|
@@ -24,3 +26,11 @@ export function getSliderResponsiveParams({ contentLength, slidesToShow, mobileF
|
|
|
24
26
|
return res;
|
|
25
27
|
}, {});
|
|
26
28
|
}
|
|
29
|
+
export const useMemoized = (value) => {
|
|
30
|
+
const [memoizedValue, setMemoizedValue] = useState(value);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
setMemoizedValue((memoized) => value && typeof value === 'object' && isEqual(memoized, value) ? memoized : value);
|
|
33
|
+
}, [value]);
|
|
34
|
+
return memoizedValue;
|
|
35
|
+
};
|
|
36
|
+
export const setElementAtrributes = (element, attributes) => Object.entries(attributes).forEach(([attribute, value]) => element.setAttribute(attribute, String(value)));
|