@gravity-ui/page-constructor 5.26.1 → 5.27.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +54 -0
  2. package/build/cjs/blocks/Banner/Banner.js +2 -2
  3. package/build/cjs/blocks/HeaderSlider/HeaderSlider.css +0 -10
  4. package/build/cjs/blocks/HeaderSlider/HeaderSlider.js +2 -2
  5. package/build/cjs/blocks/Slider/Slider.css +2 -0
  6. package/build/cjs/blocks/Slider/Slider.d.ts +1 -0
  7. package/build/cjs/blocks/Slider/Slider.js +85 -31
  8. package/build/cjs/blocks/Slider/i18n/en.json +3 -1
  9. package/build/cjs/blocks/Slider/i18n/index.d.ts +1 -1
  10. package/build/cjs/blocks/Slider/i18n/ru.json +3 -1
  11. package/build/cjs/blocks/Slider/utils.d.ts +10 -0
  12. package/build/cjs/blocks/Slider/utils.js +85 -1
  13. package/build/cjs/blocks/SliderNew/Arrow/Arrow.css +23 -19
  14. package/build/cjs/blocks/SliderNew/Arrow/Arrow.d.ts +4 -1
  15. package/build/cjs/blocks/SliderNew/Arrow/Arrow.js +5 -4
  16. package/build/cjs/blocks/SliderNew/Slider.css +103 -22
  17. package/build/cjs/blocks/SliderNew/Slider.d.ts +2 -1
  18. package/build/cjs/blocks/SliderNew/Slider.js +22 -9
  19. package/build/cjs/blocks/SliderNew/i18n/en.json +3 -1
  20. package/build/cjs/blocks/SliderNew/i18n/index.d.ts +1 -1
  21. package/build/cjs/blocks/SliderNew/i18n/ru.json +3 -1
  22. package/build/cjs/blocks/SliderNew/useSlider.d.ts +8 -6
  23. package/build/cjs/blocks/SliderNew/useSlider.js +4 -2
  24. package/build/cjs/blocks/SliderNew/useSliderPagination.d.ts +9 -0
  25. package/build/cjs/blocks/SliderNew/useSliderPagination.js +36 -0
  26. package/build/cjs/blocks/SliderNew/utils.d.ts +2 -0
  27. package/build/cjs/blocks/SliderNew/utils.js +13 -1
  28. package/build/cjs/components/FullscreenImage/FullscreenImage.css +48 -8
  29. package/build/cjs/components/FullscreenImage/FullscreenImage.d.ts +5 -0
  30. package/build/cjs/components/FullscreenImage/FullscreenImage.js +17 -3
  31. package/build/cjs/components/Media/Image/Image.d.ts +1 -0
  32. package/build/cjs/components/Media/Image/Image.js +7 -5
  33. package/build/cjs/components/Media/Media.css +4 -0
  34. package/build/cjs/components/Media/Media.d.ts +1 -0
  35. package/build/cjs/components/Media/Media.js +3 -2
  36. package/build/cjs/components/MediaBase/MediaBase.js +1 -1
  37. package/build/cjs/components/ReactPlayer/ReactPlayer.js +1 -1
  38. package/build/cjs/constructor-items.d.ts +1 -1
  39. package/build/cjs/containers/PageConstructor/PageConstructor.js +3 -1
  40. package/build/cjs/context/projectSettingsContext/ProjectSettingsContext.d.ts +1 -0
  41. package/build/cjs/models/constructor-items/blocks.d.ts +2 -1
  42. package/build/cjs/models/constructor-items/blocks.js +1 -0
  43. package/build/cjs/models/constructor-items/sub-blocks.d.ts +2 -1
  44. package/build/cjs/navigation/hooks/useShowBorder.js +3 -2
  45. package/build/cjs/sub-blocks/BannerCard/BannerCard.js +3 -3
  46. package/build/cjs/sub-blocks/Content/Content.css +14 -4
  47. package/build/cjs/sub-blocks/ImageCard/ImageCard.css +8 -0
  48. package/build/esm/blocks/Banner/Banner.js +2 -2
  49. package/build/esm/blocks/HeaderSlider/HeaderSlider.css +0 -10
  50. package/build/esm/blocks/HeaderSlider/HeaderSlider.js +1 -1
  51. package/build/esm/blocks/Slider/Slider.css +2 -0
  52. package/build/esm/blocks/Slider/Slider.d.ts +1 -0
  53. package/build/esm/blocks/Slider/Slider.js +86 -32
  54. package/build/esm/blocks/Slider/i18n/en.json +3 -1
  55. package/build/esm/blocks/Slider/i18n/index.d.ts +1 -1
  56. package/build/esm/blocks/Slider/i18n/ru.json +3 -1
  57. package/build/esm/blocks/Slider/utils.d.ts +10 -0
  58. package/build/esm/blocks/Slider/utils.js +82 -0
  59. package/build/esm/blocks/SliderNew/Arrow/Arrow.css +23 -19
  60. package/build/esm/blocks/SliderNew/Arrow/Arrow.d.ts +4 -1
  61. package/build/esm/blocks/SliderNew/Arrow/Arrow.js +5 -4
  62. package/build/esm/blocks/SliderNew/Slider.css +103 -22
  63. package/build/esm/blocks/SliderNew/Slider.d.ts +2 -1
  64. package/build/esm/blocks/SliderNew/Slider.js +22 -9
  65. package/build/esm/blocks/SliderNew/i18n/en.json +3 -1
  66. package/build/esm/blocks/SliderNew/i18n/index.d.ts +1 -1
  67. package/build/esm/blocks/SliderNew/i18n/ru.json +3 -1
  68. package/build/esm/blocks/SliderNew/useSlider.d.ts +8 -6
  69. package/build/esm/blocks/SliderNew/useSlider.js +6 -3
  70. package/build/esm/blocks/SliderNew/useSliderPagination.d.ts +9 -0
  71. package/build/esm/blocks/SliderNew/useSliderPagination.js +32 -0
  72. package/build/esm/blocks/SliderNew/utils.d.ts +2 -0
  73. package/build/esm/blocks/SliderNew/utils.js +10 -0
  74. package/build/esm/components/FullscreenImage/FullscreenImage.css +48 -8
  75. package/build/esm/components/FullscreenImage/FullscreenImage.d.ts +5 -0
  76. package/build/esm/components/FullscreenImage/FullscreenImage.js +18 -4
  77. package/build/esm/components/Media/Image/Image.d.ts +1 -0
  78. package/build/esm/components/Media/Image/Image.js +7 -5
  79. package/build/esm/components/Media/Media.css +4 -0
  80. package/build/esm/components/Media/Media.d.ts +1 -0
  81. package/build/esm/components/Media/Media.js +3 -2
  82. package/build/esm/components/MediaBase/MediaBase.js +1 -1
  83. package/build/esm/components/ReactPlayer/ReactPlayer.js +1 -1
  84. package/build/esm/constructor-items.d.ts +1 -1
  85. package/build/esm/containers/PageConstructor/PageConstructor.js +4 -2
  86. package/build/esm/context/projectSettingsContext/ProjectSettingsContext.d.ts +1 -0
  87. package/build/esm/models/constructor-items/blocks.d.ts +2 -1
  88. package/build/esm/models/constructor-items/blocks.js +1 -0
  89. package/build/esm/models/constructor-items/sub-blocks.d.ts +2 -1
  90. package/build/esm/navigation/hooks/useShowBorder.js +1 -1
  91. package/build/esm/sub-blocks/BannerCard/BannerCard.js +3 -3
  92. package/build/esm/sub-blocks/Content/Content.css +14 -4
  93. package/build/esm/sub-blocks/ImageCard/ImageCard.css +8 -0
  94. package/package.json +4 -1
  95. package/server/models/constructor-items/blocks.d.ts +2 -1
  96. package/server/models/constructor-items/blocks.js +1 -0
  97. package/server/models/constructor-items/sub-blocks.d.ts +2 -1
  98. package/styles/mixins.scss +1 -1
  99. 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-arrow__button {
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-arrow__button:hover {
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-arrow__button, .pc-slider-new-block-arrow {
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-arrow:hover .pc-slider-new-block-arrow__button {
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({ type }, className) },
8
- React.createElement("button", { className: b('button'), onClick: onClick, "aria-label": i18n(`arrow-${type}`) },
9
- React.createElement("span", { className: b('icon-wrapper') },
10
- React.createElement(ToggleArrow, { size: size, type: 'horizontal', iconType: "navigation", className: b('icon') })))));
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-SliderNewBlock_type_media-card_one-slide) {
724
+ .pc-SliderNewBlock_type_media-card:not(.pc-SliderNewBlock_one-slide) {
716
725
  margin-left: 0;
717
726
  padding-left: 0;
718
727
  width: 100%;
@@ -746,14 +755,6 @@ unpredictable css rules order in build */
746
755
  .pc-SliderNewBlock_type_header-card {
747
756
  padding-top: 0;
748
757
  }
749
- @media (max-width: 577px) {
750
- .pc-SliderNewBlock_type_header-card:not(.pc-SliderNewBlock_type_header-card_one-slide) {
751
- margin-left: 0;
752
- padding-left: 0;
753
- width: 100%;
754
- overflow: inherit;
755
- }
756
- }
757
758
  .pc-SliderNewBlock_type_header-card .pc-SliderNewBlock__wrapper {
758
759
  position: relative;
759
760
  }
@@ -775,32 +776,109 @@ unpredictable css rules order in build */
775
776
  left: 0;
776
777
  margin-right: 0;
777
778
  }
778
- .pc-SliderNewBlock_type_header-card .pc-SliderNewBlock__arrow button {
779
- background-color: transparent;
780
- box-shadow: none;
779
+ .pc-SliderNewBlock_type_header-card:has(.swiper-slide-active .pc-header-block_controls-view_light) .pc-slider-new-block-arrow__inner {
780
+ color: var(--g-color-text-dark-primary);
781
+ }
782
+ .pc-SliderNewBlock_type_header-card:has(.swiper-slide-active .pc-header-block_controls-view_light) .pc-SliderNewBlock__dot {
783
+ background-color: var(--g-color-private-black-150);
784
+ }
785
+ .pc-SliderNewBlock_type_header-card:has(.swiper-slide-active .pc-header-block_controls-view_light) .pc-SliderNewBlock__dot_active {
786
+ background-color: var(--g-color-private-black-300);
787
+ }
788
+ .pc-SliderNewBlock_type_header-card:has(.swiper-slide-active .pc-header-block_controls-view_dark) .pc-slider-new-block-arrow__inner {
789
+ color: var(--g-color-text-light-primary);
781
790
  }
782
- .pc-SliderNewBlock_type_header-card .pc-SliderNewBlock__arrow button:hover {
783
- box-shadow: none;
791
+ .pc-SliderNewBlock_type_header-card:has(.swiper-slide-active .pc-header-block_controls-view_dark) .pc-SliderNewBlock__dot {
792
+ background-color: var(--g-color-private-white-150);
784
793
  }
785
- .pc-SliderNewBlock_type_header-card .pc-SliderNewBlock__arrow:hover button {
786
- box-shadow: none;
794
+ .pc-SliderNewBlock_type_header-card:has(.swiper-slide-active .pc-header-block_controls-view_dark) .pc-SliderNewBlock__dot_active {
795
+ background-color: var(--g-color-private-white-300);
787
796
  }
788
797
  .pc-SliderNewBlock_type_header-card .pc-SliderNewBlock__slide {
789
798
  padding: 0;
790
799
  }
800
+ @media (max-width: 769px) {
801
+ .pc-SliderNewBlock_type_header-card:not(.pc-SliderNewBlock_one-slide) {
802
+ margin-left: -8px;
803
+ padding-left: 0;
804
+ width: calc(100% + 8px);
805
+ }
806
+ }
791
807
  @media (max-width: 577px) {
792
808
  .pc-SliderNewBlock_type_header-card .pc-SliderNewBlock__arrow {
793
809
  display: none;
794
810
  }
795
- .pc-SliderNewBlock_type_header-card.pc-SliderNewBlock:not(.pc-SliderNewBlock_type_header-card_one-slide) .pc-SliderNewBlock__slider {
811
+ .pc-SliderNewBlock_type_header-card:not(.pc-SliderNewBlock_one-slide) .pc-SliderNewBlock__slider {
796
812
  margin-left: 0;
797
813
  }
798
- .pc-SliderNewBlock_type_header-card.pc-SliderNewBlock:not(.pc-SliderNewBlock_type_header-card_one-slide) .pc-SliderNewBlock__slide {
799
- padding-right: 0;
814
+ .pc-SliderNewBlock_type_header-card:not(.pc-SliderNewBlock_one-slide) .swiper-wrapper {
800
815
  padding-left: 0;
801
816
  }
802
- .pc-SliderNewBlock_type_header-card.pc-SliderNewBlock:not(.pc-SliderNewBlock_type_header-card_one-slide) .pc-SliderNewBlock__slide:last-child {
817
+ .pc-SliderNewBlock_type_header-card:not(.pc-SliderNewBlock_one-slide) .pc-SliderNewBlock__slide {
803
818
  padding-right: 0;
819
+ padding-left: 0;
820
+ }
821
+ }
822
+ .pc-SliderNewBlock_type_fullscreen-card {
823
+ padding-top: 0;
824
+ }
825
+ @media (max-width: 577px) {
826
+ .pc-SliderNewBlock_type_fullscreen-card:not(.pc-SliderNewBlock_one-slide) {
827
+ margin-left: 0;
828
+ padding-left: 0;
829
+ width: 100%;
830
+ overflow: inherit;
831
+ }
832
+ }
833
+ .pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock__slider {
834
+ padding: 24px 0 40px;
835
+ height: 100vh;
836
+ margin: 0;
837
+ }
838
+ .pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock__slider .swiper-pagination {
839
+ bottom: 11px;
840
+ }
841
+ .pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock__slider .pc-SliderNewBlock__dot {
842
+ background-color: var(--g-color-text-light-hint);
843
+ }
844
+ .pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock__slider .pc-SliderNewBlock__dot_active {
845
+ background-color: var(--g-color-text-light-primary);
846
+ }
847
+ .pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock__slider .pc-SliderNewBlock__slide {
848
+ height: 100%;
849
+ padding: 0 120px;
850
+ }
851
+ .pc-SliderNewBlock_type_fullscreen-card:hover .pc-SliderNewBlock__arrow {
852
+ display: flex;
853
+ }
854
+ .pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock__arrow {
855
+ display: none;
856
+ width: 120px;
857
+ top: 40px;
858
+ bottom: 40px;
859
+ }
860
+ .pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock__arrow_prev {
861
+ left: 0;
862
+ margin-right: 0;
863
+ }
864
+ @media (max-width: 769px) {
865
+ .pc-SliderNewBlock_type_fullscreen-card {
866
+ margin-left: 0;
867
+ }
868
+ .pc-SliderNewBlock_type_fullscreen-card .pc-SliderNewBlock_slider {
869
+ margin-left: 0;
870
+ width: 100%;
871
+ }
872
+ .pc-SliderNewBlock_type_fullscreen-card:hover .pc-SliderNewBlock__arrow {
873
+ display: none;
874
+ }
875
+ }
876
+ @media (max-width: 577px) {
877
+ .pc-SliderNewBlock_type_fullscreen-card:not(.pc-SliderNewBlock_one-slide) .pc-SliderNewBlock__slider {
878
+ margin-left: 0;
879
+ }
880
+ .pc-SliderNewBlock_type_fullscreen-card:not(.pc-SliderNewBlock_one-slide) .swiper-wrapper {
881
+ padding-left: 0;
804
882
  }
805
883
  }
806
884
  @media (max-width: 769px) {
@@ -821,8 +899,11 @@ unpredictable css rules order in build */
821
899
  overflow-x: auto;
822
900
  }
823
901
  .pc-SliderNewBlock:not(.pc-SliderNewBlock_one-slide) .pc-SliderNewBlock__slider {
824
- padding: 24px 24px 48px;
825
- margin: 0 0 0 -24px;
902
+ margin-left: -24px;
903
+ margin-right: 0;
904
+ }
905
+ .pc-SliderNewBlock:not(.pc-SliderNewBlock_one-slide) .swiper-wrapper {
906
+ padding-left: 16px;
826
907
  }
827
908
  .pc-SliderNewBlock:not(.pc-SliderNewBlock_one-slide) .pc-SliderNewBlock__slide {
828
909
  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, autoplay, onSwiper, onPrev, onNext, isLocked, setIsLocked } = useSlider({
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, pagination: dots && {
31
- clickable: true,
32
- bulletClass: b('dot', dotsClassName),
33
- bulletActiveClass: b('dot_active'),
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(Arrow, { className: b('arrow', { prev: true }), type: "left", onClick: onPrev, size: arrowSize }),
37
- React.createElement(Arrow, { className: b('arrow', { next: true }), type: "right", onClick: onNext, size: arrowSize }))),
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,4 +1,6 @@
1
1
  {
2
2
  "arrow-right": "Next",
3
- "arrow-left": "Previous"
3
+ "arrow-left": "Previous",
4
+ "dot-label": "Page {{index}}",
5
+ "pagination-label": "Pages"
4
6
  }
@@ -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,4 +1,6 @@
1
1
  {
2
2
  "arrow-right": "Дальше",
3
- "arrow-left": "Назад"
3
+ "arrow-left": "Назад",
4
+ "dot-label": "Страница {{index}}",
5
+ "pagination-label": "Страницы"
4
6
  }
@@ -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
- export declare const useSlider: ({ children, autoplayMs, type, slidesToShow, }: React.PropsWithChildren<{
5
- autoplayMs?: number | undefined;
6
- type?: string | undefined;
7
- slidesToShow?: SlidesToShow | undefined;
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 | undefined;
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 = ({ children, autoplayMs, type, slidesToShow, }) => {
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 = useMemo(() => Boolean(autoplayMs), [autoplayMs]);
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)));