@gravity-ui/page-constructor 5.27.0 → 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 (88) hide show
  1. package/README.md +54 -0
  2. package/build/cjs/blocks/HeaderSlider/HeaderSlider.css +0 -10
  3. package/build/cjs/blocks/HeaderSlider/HeaderSlider.js +2 -2
  4. package/build/cjs/blocks/Slider/Slider.css +2 -0
  5. package/build/cjs/blocks/Slider/Slider.d.ts +1 -0
  6. package/build/cjs/blocks/Slider/Slider.js +85 -31
  7. package/build/cjs/blocks/Slider/i18n/en.json +3 -1
  8. package/build/cjs/blocks/Slider/i18n/index.d.ts +1 -1
  9. package/build/cjs/blocks/Slider/i18n/ru.json +3 -1
  10. package/build/cjs/blocks/Slider/utils.d.ts +10 -0
  11. package/build/cjs/blocks/Slider/utils.js +85 -1
  12. package/build/cjs/blocks/SliderNew/Arrow/Arrow.css +23 -19
  13. package/build/cjs/blocks/SliderNew/Arrow/Arrow.d.ts +4 -1
  14. package/build/cjs/blocks/SliderNew/Arrow/Arrow.js +5 -4
  15. package/build/cjs/blocks/SliderNew/Slider.css +103 -22
  16. package/build/cjs/blocks/SliderNew/Slider.d.ts +2 -1
  17. package/build/cjs/blocks/SliderNew/Slider.js +22 -9
  18. package/build/cjs/blocks/SliderNew/i18n/en.json +3 -1
  19. package/build/cjs/blocks/SliderNew/i18n/index.d.ts +1 -1
  20. package/build/cjs/blocks/SliderNew/i18n/ru.json +3 -1
  21. package/build/cjs/blocks/SliderNew/useSlider.d.ts +8 -6
  22. package/build/cjs/blocks/SliderNew/useSlider.js +4 -2
  23. package/build/cjs/blocks/SliderNew/useSliderPagination.d.ts +9 -0
  24. package/build/cjs/blocks/SliderNew/useSliderPagination.js +36 -0
  25. package/build/cjs/blocks/SliderNew/utils.d.ts +2 -0
  26. package/build/cjs/blocks/SliderNew/utils.js +13 -1
  27. package/build/cjs/components/FullscreenImage/FullscreenImage.css +48 -8
  28. package/build/cjs/components/FullscreenImage/FullscreenImage.d.ts +5 -0
  29. package/build/cjs/components/FullscreenImage/FullscreenImage.js +17 -3
  30. package/build/cjs/components/Media/Image/Image.d.ts +1 -0
  31. package/build/cjs/components/Media/Image/Image.js +7 -5
  32. package/build/cjs/components/Media/Media.css +4 -0
  33. package/build/cjs/components/Media/Media.d.ts +1 -0
  34. package/build/cjs/components/Media/Media.js +3 -2
  35. package/build/cjs/components/MediaBase/MediaBase.js +1 -1
  36. package/build/cjs/components/ReactPlayer/ReactPlayer.js +1 -1
  37. package/build/cjs/constructor-items.d.ts +1 -1
  38. package/build/cjs/models/constructor-items/blocks.d.ts +2 -1
  39. package/build/cjs/models/constructor-items/blocks.js +1 -0
  40. package/build/cjs/navigation/hooks/useShowBorder.js +3 -2
  41. package/build/cjs/sub-blocks/Content/Content.css +14 -4
  42. package/build/cjs/sub-blocks/ImageCard/ImageCard.css +8 -0
  43. package/build/esm/blocks/HeaderSlider/HeaderSlider.css +0 -10
  44. package/build/esm/blocks/HeaderSlider/HeaderSlider.js +1 -1
  45. package/build/esm/blocks/Slider/Slider.css +2 -0
  46. package/build/esm/blocks/Slider/Slider.d.ts +1 -0
  47. package/build/esm/blocks/Slider/Slider.js +86 -32
  48. package/build/esm/blocks/Slider/i18n/en.json +3 -1
  49. package/build/esm/blocks/Slider/i18n/index.d.ts +1 -1
  50. package/build/esm/blocks/Slider/i18n/ru.json +3 -1
  51. package/build/esm/blocks/Slider/utils.d.ts +10 -0
  52. package/build/esm/blocks/Slider/utils.js +82 -0
  53. package/build/esm/blocks/SliderNew/Arrow/Arrow.css +23 -19
  54. package/build/esm/blocks/SliderNew/Arrow/Arrow.d.ts +4 -1
  55. package/build/esm/blocks/SliderNew/Arrow/Arrow.js +5 -4
  56. package/build/esm/blocks/SliderNew/Slider.css +103 -22
  57. package/build/esm/blocks/SliderNew/Slider.d.ts +2 -1
  58. package/build/esm/blocks/SliderNew/Slider.js +22 -9
  59. package/build/esm/blocks/SliderNew/i18n/en.json +3 -1
  60. package/build/esm/blocks/SliderNew/i18n/index.d.ts +1 -1
  61. package/build/esm/blocks/SliderNew/i18n/ru.json +3 -1
  62. package/build/esm/blocks/SliderNew/useSlider.d.ts +8 -6
  63. package/build/esm/blocks/SliderNew/useSlider.js +6 -3
  64. package/build/esm/blocks/SliderNew/useSliderPagination.d.ts +9 -0
  65. package/build/esm/blocks/SliderNew/useSliderPagination.js +32 -0
  66. package/build/esm/blocks/SliderNew/utils.d.ts +2 -0
  67. package/build/esm/blocks/SliderNew/utils.js +10 -0
  68. package/build/esm/components/FullscreenImage/FullscreenImage.css +48 -8
  69. package/build/esm/components/FullscreenImage/FullscreenImage.d.ts +5 -0
  70. package/build/esm/components/FullscreenImage/FullscreenImage.js +18 -4
  71. package/build/esm/components/Media/Image/Image.d.ts +1 -0
  72. package/build/esm/components/Media/Image/Image.js +7 -5
  73. package/build/esm/components/Media/Media.css +4 -0
  74. package/build/esm/components/Media/Media.d.ts +1 -0
  75. package/build/esm/components/Media/Media.js +3 -2
  76. package/build/esm/components/MediaBase/MediaBase.js +1 -1
  77. package/build/esm/components/ReactPlayer/ReactPlayer.js +1 -1
  78. package/build/esm/constructor-items.d.ts +1 -1
  79. package/build/esm/models/constructor-items/blocks.d.ts +2 -1
  80. package/build/esm/models/constructor-items/blocks.js +1 -0
  81. package/build/esm/navigation/hooks/useShowBorder.js +1 -1
  82. package/build/esm/sub-blocks/Content/Content.css +14 -4
  83. package/build/esm/sub-blocks/ImageCard/ImageCard.css +8 -0
  84. package/package.json +2 -1
  85. package/server/models/constructor-items/blocks.d.ts +2 -1
  86. package/server/models/constructor-items/blocks.js +1 -0
  87. package/styles/mixins.scss +1 -1
  88. package/widget/index.js +1 -1
@@ -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)));
@@ -12,6 +12,25 @@ unpredictable css rules order in build */
12
12
  .pc-fullscreen-image__modal-content {
13
13
  position: relative;
14
14
  border-radius: var(--pc-border-radius);
15
+ width: 100%;
16
+ }
17
+ .pc-fullscreen-image__modal-content-wrapper {
18
+ width: 100%;
19
+ }
20
+ .pc-fullscreen-image__modal-content_loaded {
21
+ max-width: fit-content;
22
+ }
23
+ .pc-fullscreen-image__modal_with-slider .g-modal__content-wrapper {
24
+ width: 100%;
25
+ height: 100vh;
26
+ margin: 0;
27
+ justify-content: center;
28
+ }
29
+ .pc-fullscreen-image__modal_with-slider .pc-fullscreen-image__modal-content {
30
+ background-color: transparent;
31
+ }
32
+ .pc-fullscreen-image__modal_with-slider .pc-fullscreen-image__modal-content:hover .pc-fullscreen-image__icon-wrapper {
33
+ opacity: 1;
15
34
  }
16
35
  .pc-fullscreen-image__modal-image {
17
36
  display: block;
@@ -19,6 +38,27 @@ unpredictable css rules order in build */
19
38
  max-height: 70vh;
20
39
  overflow: hidden;
21
40
  }
41
+ .pc-fullscreen-image__modal-slider {
42
+ max-width: 100vw;
43
+ width: 100%;
44
+ height: 100vh;
45
+ }
46
+ .pc-fullscreen-image__modal-slider_item {
47
+ height: 100%;
48
+ display: flex;
49
+ justify-content: center;
50
+ align-items: center;
51
+ }
52
+ .pc-fullscreen-image__modal-slider_item-image {
53
+ display: block;
54
+ margin: auto;
55
+ border-radius: var(--pc-border-radius);
56
+ overflow: hidden;
57
+ max-height: calc(100vh - 80px);
58
+ max-width: 100%;
59
+ object-fit: contain;
60
+ object-position: center;
61
+ }
22
62
  .pc-fullscreen-image__modal .g-modal__content, .pc-fullscreen-image__modal-image {
23
63
  border-radius: var(--pc-border-radius);
24
64
  }
@@ -36,6 +76,7 @@ unpredictable css rules order in build */
36
76
  align-items: center;
37
77
  justify-content: center;
38
78
  position: absolute;
79
+ z-index: 1001;
39
80
  right: 16px;
40
81
  top: 16px;
41
82
  width: 36px;
@@ -56,6 +97,10 @@ unpredictable css rules order in build */
56
97
  .pc-fullscreen-image__icon-wrapper:focus {
57
98
  opacity: 1;
58
99
  }
100
+ .pc-fullscreen-image__icon-wrapper_visible {
101
+ right: 24px;
102
+ top: 24px;
103
+ }
59
104
  .pc-fullscreen-image__icon {
60
105
  color: var(--g-color-text-hint);
61
106
  }
@@ -67,14 +112,9 @@ unpredictable css rules order in build */
67
112
  width: 100%;
68
113
  }
69
114
  }
70
- @media (max-width: 1081px) {
71
- .pc-fullscreen-image__image {
72
- pointer-events: none;
73
- }
115
+ @media (max-width: 769px) {
74
116
  .pc-fullscreen-image__icon-wrapper {
75
- display: none;
76
- }
77
- .pc-fullscreen-image__modal {
78
- display: none !important; /* stylelint-disable-line declaration-no-important */
117
+ right: 20px;
118
+ top: 50px;
79
119
  }
80
120
  }
@@ -1,4 +1,5 @@
1
1
  import { CSSProperties, HTMLProps } from 'react';
2
+ import { ImageProps as ModelImageProps } from '../../models';
2
3
  import { ImageProps } from '../Image/Image';
3
4
  import './FullscreenImage.css';
4
5
  export interface FullscreenImageProps extends ImageProps {
@@ -6,6 +7,10 @@ export interface FullscreenImageProps extends ImageProps {
6
7
  modalImageClass?: string;
7
8
  imageStyle?: CSSProperties;
8
9
  extraProps?: HTMLProps<HTMLDivElement>;
10
+ sliderData?: {
11
+ items: ModelImageProps[];
12
+ initialIndex: number;
13
+ };
9
14
  }
10
15
  declare const FullscreenImage: (props: FullscreenImageProps) => JSX.Element;
11
16
  export default FullscreenImage;
@@ -1,26 +1,40 @@
1
- import React, { useState } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import { ChevronsExpandUpRight, Xmark } from '@gravity-ui/icons';
3
3
  import { Icon, Modal } from '@gravity-ui/uikit';
4
+ import { SliderNewBlock as SliderBlock } from '../../blocks/unstable';
5
+ import { SliderType } from '../../models';
4
6
  import { block } from '../../utils';
5
7
  import Image from '../Image/Image';
8
+ import { getMediaImage } from '../Media/Image/utils';
6
9
  import { i18n } from './i18n';
7
10
  import './FullscreenImage.css';
8
11
  const b = block('fullscreen-image');
9
12
  const FULL_SCREEN_ICON_SIZE = 18;
10
13
  const CLOSE_ICON_SIZE = 24;
11
14
  const FullscreenImage = (props) => {
12
- const { imageClassName, modalImageClass, imageStyle, alt = i18n('img-alt'), extraProps } = props;
15
+ const { imageClassName, sliderData, modalImageClass, imageStyle, alt = i18n('img-alt'), extraProps, } = props;
13
16
  const [isOpened, setIsOpened] = useState(false);
17
+ const [sliderLoaded, setSliderLoaded] = useState(false);
14
18
  const openModal = () => setIsOpened(true);
15
19
  const closeModal = () => setIsOpened(false);
20
+ useEffect(() => {
21
+ if (sliderData && !isOpened) {
22
+ setSliderLoaded(false);
23
+ }
24
+ }, [isOpened, sliderData]);
25
+ const handleSliderImageLoad = () => {
26
+ setSliderLoaded(true);
27
+ };
16
28
  return (React.createElement("div", Object.assign({ className: b() }, extraProps),
17
29
  React.createElement("div", { className: b('image-wrapper') },
18
30
  React.createElement(Image, Object.assign({}, props, { alt: alt, className: b('image', imageClassName), onClick: openModal, style: imageStyle })),
19
31
  React.createElement("button", { className: b('icon-wrapper'), onClick: openModal },
20
32
  React.createElement(Icon, { data: ChevronsExpandUpRight, width: FULL_SCREEN_ICON_SIZE, height: FULL_SCREEN_ICON_SIZE, className: b('icon') }))),
21
- isOpened && (React.createElement(Modal, { open: isOpened, onClose: closeModal, className: b('modal'), contentClassName: b('modal-content') },
33
+ isOpened && (React.createElement(Modal, { open: isOpened, onClose: closeModal, className: b('modal', { 'with-slider': Boolean(sliderData) }), contentClassName: b('modal-content', { loaded: sliderLoaded }) },
22
34
  React.createElement("button", { className: b('icon-wrapper', { visible: true }), onClick: closeModal, "aria-label": i18n('close') },
23
35
  React.createElement(Icon, { data: Xmark, width: CLOSE_ICON_SIZE, height: CLOSE_ICON_SIZE, className: b('icon', { hover: true }) })),
24
- React.createElement(Image, Object.assign({}, props, { className: b('modal-image', modalImageClass) }))))));
36
+ sliderData ? (React.createElement("div", { className: b('modal-slider') },
37
+ React.createElement(SliderBlock, { initialSlide: sliderData.initialIndex, slidesToShow: 1, type: SliderType.FullscreenCard }, sliderData.items.map((item, index) => (React.createElement("div", { key: index, className: b('modal-slider_item') },
38
+ React.createElement(Image, Object.assign({ onLoad: handleSliderImageLoad, className: b('modal-slider_item-image', modalImageClass), containerClassName: b('modal-slider_item-image-wrapper') }, getMediaImage(item))))))))) : (React.createElement(Image, Object.assign({}, props, { className: b('modal-image', modalImageClass) })))))));
25
39
  };
26
40
  export default FullscreenImage;