@alfalab/core-components-gallery 7.1.10 → 7.2.0-alfasans

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 (140) hide show
  1. package/Component.js +6 -3
  2. package/Component.js.map +1 -1
  3. package/components/bottom-button/index.css +5 -5
  4. package/components/bottom-button/index.module.css.js +1 -1
  5. package/components/buttons/index.css +5 -5
  6. package/components/buttons/index.module.css.js +1 -1
  7. package/components/header/index.css +1 -1
  8. package/components/header/index.module.css.js +1 -1
  9. package/components/header-info-block/index.css +4 -4
  10. package/components/header-info-block/index.module.css.js +1 -1
  11. package/components/header-mobile/index.css +6 -6
  12. package/components/header-mobile/index.module.css.js +1 -1
  13. package/components/image-preview/index.css +17 -17
  14. package/components/image-preview/index.module.css.js +1 -1
  15. package/components/image-viewer/component.js +30 -21
  16. package/components/image-viewer/component.js.map +1 -1
  17. package/components/image-viewer/index.css +85 -37
  18. package/components/image-viewer/index.module.css.js +1 -1
  19. package/components/image-viewer/index.module.css.js.map +1 -1
  20. package/components/image-viewer/single.js +2 -1
  21. package/components/image-viewer/single.js.map +1 -1
  22. package/components/image-viewer/slide.d.ts +1 -0
  23. package/components/image-viewer/slide.js +17 -13
  24. package/components/image-viewer/slide.js.map +1 -1
  25. package/components/image-viewer/video/index.css +13 -8
  26. package/components/image-viewer/video/index.module.css.js +1 -1
  27. package/components/image-viewer/video/index.module.css.js.map +1 -1
  28. package/components/info-bar/index.css +3 -3
  29. package/components/info-bar/index.module.css.js +1 -1
  30. package/components/navigation-bar/index.css +8 -8
  31. package/components/navigation-bar/index.module.css.js +1 -1
  32. package/components/subtitles/index.css +3 -3
  33. package/components/subtitles/index.module.css.js +1 -1
  34. package/cssm/Component.js +6 -3
  35. package/cssm/Component.js.map +1 -1
  36. package/cssm/components/image-viewer/component.js +30 -21
  37. package/cssm/components/image-viewer/component.js.map +1 -1
  38. package/cssm/components/image-viewer/index.module.css +66 -18
  39. package/cssm/components/image-viewer/single.js +2 -1
  40. package/cssm/components/image-viewer/single.js.map +1 -1
  41. package/cssm/components/image-viewer/slide.d.ts +1 -0
  42. package/cssm/components/image-viewer/slide.js +17 -13
  43. package/cssm/components/image-viewer/slide.js.map +1 -1
  44. package/cssm/components/image-viewer/video/index.module.css +6 -1
  45. package/cssm/index.module.css +2 -0
  46. package/esm/Component.js +6 -3
  47. package/esm/Component.js.map +1 -1
  48. package/esm/components/bottom-button/index.css +5 -5
  49. package/esm/components/bottom-button/index.module.css.js +1 -1
  50. package/esm/components/buttons/index.css +5 -5
  51. package/esm/components/buttons/index.module.css.js +1 -1
  52. package/esm/components/header/index.css +1 -1
  53. package/esm/components/header/index.module.css.js +1 -1
  54. package/esm/components/header-info-block/index.css +4 -4
  55. package/esm/components/header-info-block/index.module.css.js +1 -1
  56. package/esm/components/header-mobile/index.css +6 -6
  57. package/esm/components/header-mobile/index.module.css.js +1 -1
  58. package/esm/components/image-preview/index.css +17 -17
  59. package/esm/components/image-preview/index.module.css.js +1 -1
  60. package/esm/components/image-viewer/component.js +31 -22
  61. package/esm/components/image-viewer/component.js.map +1 -1
  62. package/esm/components/image-viewer/index.css +85 -37
  63. package/esm/components/image-viewer/index.module.css.js +1 -1
  64. package/esm/components/image-viewer/index.module.css.js.map +1 -1
  65. package/esm/components/image-viewer/single.js +3 -2
  66. package/esm/components/image-viewer/single.js.map +1 -1
  67. package/esm/components/image-viewer/slide.d.ts +1 -0
  68. package/esm/components/image-viewer/slide.js +18 -14
  69. package/esm/components/image-viewer/slide.js.map +1 -1
  70. package/esm/components/image-viewer/video/index.css +13 -8
  71. package/esm/components/image-viewer/video/index.module.css.js +1 -1
  72. package/esm/components/image-viewer/video/index.module.css.js.map +1 -1
  73. package/esm/components/info-bar/index.css +3 -3
  74. package/esm/components/info-bar/index.module.css.js +1 -1
  75. package/esm/components/navigation-bar/index.css +8 -8
  76. package/esm/components/navigation-bar/index.module.css.js +1 -1
  77. package/esm/components/subtitles/index.css +3 -3
  78. package/esm/components/subtitles/index.module.css.js +1 -1
  79. package/esm/index.css +11 -9
  80. package/esm/index.module.css.js +1 -1
  81. package/esm/index.module.css.js.map +1 -1
  82. package/index.css +11 -9
  83. package/index.module.css.js +1 -1
  84. package/index.module.css.js.map +1 -1
  85. package/modern/Component.js +6 -3
  86. package/modern/Component.js.map +1 -1
  87. package/modern/components/bottom-button/index.css +5 -5
  88. package/modern/components/bottom-button/index.module.css.js +1 -1
  89. package/modern/components/buttons/index.css +5 -5
  90. package/modern/components/buttons/index.module.css.js +1 -1
  91. package/modern/components/header/index.css +1 -1
  92. package/modern/components/header/index.module.css.js +1 -1
  93. package/modern/components/header-info-block/index.css +4 -4
  94. package/modern/components/header-info-block/index.module.css.js +1 -1
  95. package/modern/components/header-mobile/index.css +6 -6
  96. package/modern/components/header-mobile/index.module.css.js +1 -1
  97. package/modern/components/image-preview/index.css +17 -17
  98. package/modern/components/image-preview/index.module.css.js +1 -1
  99. package/modern/components/image-viewer/component.js +21 -13
  100. package/modern/components/image-viewer/component.js.map +1 -1
  101. package/modern/components/image-viewer/index.css +85 -37
  102. package/modern/components/image-viewer/index.module.css.js +1 -1
  103. package/modern/components/image-viewer/index.module.css.js.map +1 -1
  104. package/modern/components/image-viewer/single.js +3 -2
  105. package/modern/components/image-viewer/single.js.map +1 -1
  106. package/modern/components/image-viewer/slide.d.ts +1 -0
  107. package/modern/components/image-viewer/slide.js +11 -7
  108. package/modern/components/image-viewer/slide.js.map +1 -1
  109. package/modern/components/image-viewer/video/index.css +13 -8
  110. package/modern/components/image-viewer/video/index.module.css.js +1 -1
  111. package/modern/components/image-viewer/video/index.module.css.js.map +1 -1
  112. package/modern/components/info-bar/index.css +3 -3
  113. package/modern/components/info-bar/index.module.css.js +1 -1
  114. package/modern/components/navigation-bar/index.css +8 -8
  115. package/modern/components/navigation-bar/index.module.css.js +1 -1
  116. package/modern/components/subtitles/index.css +3 -3
  117. package/modern/components/subtitles/index.module.css.js +1 -1
  118. package/modern/index.css +11 -9
  119. package/modern/index.module.css.js +1 -1
  120. package/modern/index.module.css.js.map +1 -1
  121. package/moderncssm/Component.js +6 -3
  122. package/moderncssm/Component.js.map +1 -1
  123. package/moderncssm/components/image-viewer/component.js +21 -13
  124. package/moderncssm/components/image-viewer/component.js.map +1 -1
  125. package/moderncssm/components/image-viewer/index.module.css +65 -17
  126. package/moderncssm/components/image-viewer/single.js +3 -2
  127. package/moderncssm/components/image-viewer/single.js.map +1 -1
  128. package/moderncssm/components/image-viewer/slide.d.ts +1 -0
  129. package/moderncssm/components/image-viewer/slide.js +11 -7
  130. package/moderncssm/components/image-viewer/slide.js.map +1 -1
  131. package/moderncssm/components/image-viewer/video/index.module.css +6 -1
  132. package/moderncssm/index.module.css +2 -0
  133. package/package.json +11 -11
  134. package/src/Component.tsx +8 -7
  135. package/src/components/image-viewer/component.tsx +62 -41
  136. package/src/components/image-viewer/index.module.css +60 -15
  137. package/src/components/image-viewer/single.tsx +14 -6
  138. package/src/components/image-viewer/slide.tsx +24 -5
  139. package/src/components/image-viewer/video/index.module.css +5 -1
  140. package/src/index.module.css +2 -0
@@ -13,7 +13,7 @@
13
13
  --gap-12: var(--gap-s);
14
14
  --gap-24: var(--gap-xl);
15
15
  }
16
- .gallery__component_3ax0x {
16
+ .gallery__component_1qpjj {
17
17
  display: flex;
18
18
  flex-wrap: nowrap;
19
19
  align-content: center;
@@ -25,25 +25,25 @@
25
25
  scrollbar-width: none;
26
26
  background-color: var(--color-static-neutral-0-inverted);
27
27
  }
28
- .gallery__component_3ax0x.gallery__mobile_3ax0x {
28
+ .gallery__component_1qpjj.gallery__mobile_1qpjj {
29
29
  padding: var(--gap-8) var(--gap-24);
30
30
  }
31
- .gallery__component_3ax0x::-webkit-scrollbar {
31
+ .gallery__component_1qpjj::-webkit-scrollbar {
32
32
  display: none;
33
33
  }
34
- .gallery__previews_3ax0x {
34
+ .gallery__previews_1qpjj {
35
35
  display: flex;
36
36
  }
37
- .gallery__preview_3ax0x {
37
+ .gallery__preview_1qpjj {
38
38
  flex-shrink: 0;
39
39
  margin-right: var(--gap-4);
40
40
  }
41
- .gallery__preview_3ax0x.gallery__mobile_3ax0x {
41
+ .gallery__preview_1qpjj.gallery__mobile_1qpjj {
42
42
  margin-right: var(--gap-2);
43
43
  }
44
- .gallery__preview_3ax0x:first-child {
44
+ .gallery__preview_1qpjj:first-child {
45
45
  margin-left: auto;
46
46
  }
47
- .gallery__preview_3ax0x:last-child {
47
+ .gallery__preview_1qpjj:last-child {
48
48
  margin-right: auto;
49
49
  }
@@ -1,6 +1,6 @@
1
1
  import './index.css';
2
2
 
3
- const styles = {"component":"gallery__component_3ax0x","mobile":"gallery__mobile_3ax0x","preview":"gallery__preview_3ax0x"};
3
+ const styles = {"component":"gallery__component_1qpjj","mobile":"gallery__mobile_1qpjj","preview":"gallery__preview_1qpjj"};
4
4
 
5
5
  export { styles as default };
6
6
  //# sourceMappingURL=index.module.css.js.map
@@ -5,7 +5,7 @@
5
5
  --gap-16: var(--gap-m);
6
6
  --gap-32: var(--gap-2xl);
7
7
  }
8
- .gallery__subtitles_k5m0k {
8
+ .gallery__subtitles_1lymx {
9
9
  position: absolute;
10
10
  align-self: flex-end;
11
11
  padding: var(--gap-0) var(--gap-32);
@@ -18,10 +18,10 @@
18
18
  opacity 500ms ease-in-out,
19
19
  margin-bottom 270ms ease-in-out;
20
20
  }
21
- .gallery__subtitles_k5m0k.gallery__mobile_k5m0k {
21
+ .gallery__subtitles_1lymx.gallery__mobile_1lymx {
22
22
  position: static;
23
23
  position: initial;
24
24
  }
25
- .gallery__hideSubtitles_k5m0k {
25
+ .gallery__hideSubtitles_1lymx {
26
26
  opacity: 0;
27
27
  }
@@ -1,6 +1,6 @@
1
1
  import './index.css';
2
2
 
3
- const styles = {"subtitles":"gallery__subtitles_k5m0k","mobile":"gallery__mobile_k5m0k","hideSubtitles":"gallery__hideSubtitles_k5m0k"};
3
+ const styles = {"subtitles":"gallery__subtitles_1lymx","mobile":"gallery__mobile_1lymx","hideSubtitles":"gallery__hideSubtitles_1lymx"};
4
4
 
5
5
  export { styles as default };
6
6
  //# sourceMappingURL=index.module.css.js.map
package/modern/index.css CHANGED
@@ -13,7 +13,7 @@
13
13
  --sat: env(safe-area-inset-top, var(--gap-0));
14
14
  --sab: env(safe-area-inset-bottom, var(--gap-0));
15
15
  }
16
- .gallery__container_1bs89 {
16
+ .gallery__container_41lre {
17
17
  position: relative;
18
18
  overflow-x: hidden;
19
19
  overflow-y: auto;
@@ -21,21 +21,23 @@
21
21
  flex-direction: column;
22
22
  justify-content: space-between;
23
23
  height: 100%;
24
+ height: 100dvh;
24
25
  width: 100%;
25
26
  background-color: var(--color-static-neutral-0-inverted);
26
27
  padding-top: var(--sat);
27
28
  padding-bottom: var(--sab);
28
29
  }
29
- .gallery__container_1bs89.gallery__mobile_1bs89 {
30
+ .gallery__container_41lre.gallery__mobile_41lre {
30
31
  overflow: hidden;
31
32
  }
32
- .gallery__modal_1bs89 {
33
+ .gallery__modal_41lre {
33
34
  flex-grow: 1;
34
35
  width: 100vw;
35
36
  height: 100vh;
37
+ height: 100dvh;
36
38
  background: transparent;
37
39
  }
38
- .gallery__navigationVideo_1bs89 {
40
+ .gallery__navigationVideo_41lre {
39
41
  z-index: 3;
40
42
  width: 100%;
41
43
  position: absolute;
@@ -44,18 +46,18 @@
44
46
  transition: transform 0.3s ease-in-out;
45
47
  text-align: center;
46
48
  }
47
- .gallery__hide_1bs89 {
49
+ .gallery__hide_41lre {
48
50
  transform: translateY(114px);
49
51
  }
50
- .gallery__hideInfo_1bs89 {
52
+ .gallery__hideInfo_41lre {
51
53
  transform: translateY(48px);
52
54
  }
53
- .gallery__bottomButton_1bs89 {
55
+ .gallery__bottomButton_41lre {
54
56
  width: calc(100% - var(--gap-32));
55
57
  margin: var(--gap-16);
56
58
  background-color: var(--color-static-neutral-translucent-500-inverted);
57
59
  }
58
- .gallery__subtitles_1bs89 {
60
+ .gallery__subtitles_41lre {
59
61
  padding: var(--gap-0) var(--gap-32);
60
62
  margin-bottom: var(--gap-16);
61
63
  width: 100%;
@@ -66,6 +68,6 @@
66
68
  opacity 500ms ease-in-out,
67
69
  margin-bottom 270ms ease-in-out;
68
70
  }
69
- .gallery__hideSubtitles_1bs89 {
71
+ .gallery__hideSubtitles_41lre {
70
72
  opacity: 0;
71
73
  }
@@ -1,6 +1,6 @@
1
1
  import './index.css';
2
2
 
3
- const styles = {"container":"gallery__container_1bs89","mobile":"gallery__mobile_1bs89","modal":"gallery__modal_1bs89","navigationVideo":"gallery__navigationVideo_1bs89","hide":"gallery__hide_1bs89","hideInfo":"gallery__hideInfo_1bs89","bottomButton":"gallery__bottomButton_1bs89"};
3
+ const styles = {"container":"gallery__container_41lre","mobile":"gallery__mobile_41lre","modal":"gallery__modal_41lre","navigationVideo":"gallery__navigationVideo_41lre","hide":"gallery__hide_41lre","hideInfo":"gallery__hideInfo_41lre","bottomButton":"gallery__bottomButton_41lre"};
4
4
 
5
5
  export { styles as default };
6
6
  //# sourceMappingURL=index.module.css.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.module.css.js","sources":["src/index.module.css"],"sourcesContent":["@import '@alfalab/core-components-vars/src/index.css';\n@import '@alfalab/core-components-vars/src/safe-area.css';\n\n.container {\n position: relative;\n overflow-x: hidden;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n height: 100%;\n width: 100%;\n background-color: var(--color-static-neutral-0-inverted);\n padding-top: var(--sat);\n padding-bottom: var(--sab);\n\n &.mobile {\n overflow: hidden;\n }\n}\n\n.modal {\n flex-grow: 1;\n width: 100vw;\n height: 100vh;\n background: transparent;\n}\n\n.navigationVideo {\n z-index: 3;\n width: 100%;\n position: absolute;\n bottom: 0;\n left: 0;\n transition: transform 0.3s ease-in-out;\n text-align: center;\n}\n\n.hide {\n transform: translateY(114px);\n}\n\n.hideInfo {\n transform: translateY(48px);\n}\n\n.bottomButton {\n width: calc(100% - var(--gap-32));\n margin: var(--gap-16);\n background-color: var(--color-static-neutral-translucent-500-inverted);\n}\n\n.subtitles {\n padding: var(--gap-0) var(--gap-32);\n margin-bottom: var(--gap-16);\n width: 100%;\n text-align: center;\n opacity: 1;\n z-index: 1;\n transition:\n opacity 500ms ease-in-out,\n margin-bottom 270ms ease-in-out;\n}\n\n.hideSubtitles {\n opacity: 0;\n}\n"],"names":[],"mappings":";;AAEgB,eAAe,CAAC,WAAW,CAAC,0BAA0B,CAAC,QAAQ,CAAC,uBAAuB,CAAC,OAAO,CAAC,sBAAsB,CAAC,iBAAiB,CAAC,gCAAgC,CAAC,MAAM,CAAC,qBAAqB,CAAC,UAAU,CAAC,yBAAyB,CAAC,cAAc,CAAC,6BAAmH,CAAC;;;;"}
1
+ {"version":3,"file":"index.module.css.js","sources":["src/index.module.css"],"sourcesContent":["@import '@alfalab/core-components-vars/src/index.css';\n@import '@alfalab/core-components-vars/src/safe-area.css';\n\n.container {\n position: relative;\n overflow-x: hidden;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n height: 100%;\n height: 100dvh;\n width: 100%;\n background-color: var(--color-static-neutral-0-inverted);\n padding-top: var(--sat);\n padding-bottom: var(--sab);\n\n &.mobile {\n overflow: hidden;\n }\n}\n\n.modal {\n flex-grow: 1;\n width: 100vw;\n height: 100vh;\n height: 100dvh;\n background: transparent;\n}\n\n.navigationVideo {\n z-index: 3;\n width: 100%;\n position: absolute;\n bottom: 0;\n left: 0;\n transition: transform 0.3s ease-in-out;\n text-align: center;\n}\n\n.hide {\n transform: translateY(114px);\n}\n\n.hideInfo {\n transform: translateY(48px);\n}\n\n.bottomButton {\n width: calc(100% - var(--gap-32));\n margin: var(--gap-16);\n background-color: var(--color-static-neutral-translucent-500-inverted);\n}\n\n.subtitles {\n padding: var(--gap-0) var(--gap-32);\n margin-bottom: var(--gap-16);\n width: 100%;\n text-align: center;\n opacity: 1;\n z-index: 1;\n transition:\n opacity 500ms ease-in-out,\n margin-bottom 270ms ease-in-out;\n}\n\n.hideSubtitles {\n opacity: 0;\n}\n"],"names":[],"mappings":";;AAEgB,eAAe,CAAC,WAAW,CAAC,0BAA0B,CAAC,QAAQ,CAAC,uBAAuB,CAAC,OAAO,CAAC,sBAAsB,CAAC,iBAAiB,CAAC,gCAAgC,CAAC,MAAM,CAAC,qBAAqB,CAAC,UAAU,CAAC,yBAAyB,CAAC,cAAc,CAAC,6BAAmH,CAAC;;;;"}
@@ -62,9 +62,12 @@ const Gallery = ({ open, images, slideIndex, initialSlide = 0, loop = true, onCl
62
62
  slideTo(nextIndex);
63
63
  }, [images.length, loop, currentSlideIndex, slideTo]);
64
64
  const setImageMeta = useCallback((meta, index) => {
65
- imagesMeta[index] = meta;
66
- setImagesMeta(imagesMeta.slice());
67
- }, [imagesMeta]);
65
+ setImagesMeta((prevImagesMeta) => {
66
+ const nextImagesMeta = prevImagesMeta.slice();
67
+ nextImagesMeta[index] = meta;
68
+ return nextImagesMeta;
69
+ });
70
+ }, []);
68
71
  const handleBottomButtonClick = useCallback((e) => {
69
72
  e.stopPropagation();
70
73
  if (bottomButton?.onClick) {
@@ -1 +1 @@
1
- {"version":3,"file":"Component.js","sources":["../src/Component.tsx"],"sourcesContent":["import React, { type FC, type MouseEvent, useCallback, useEffect, useState } from 'react';\nimport cn from 'classnames';\nimport type SwiperCore from 'swiper';\n\nimport { BaseModal } from '@alfalab/core-components-base-modal';\nimport { useIsDesktop } from '@alfalab/core-components-mq';\n\nimport { BottomButton } from './components/bottom-button';\nimport { Single } from './components/image-viewer/single';\nimport { Subtitles } from './components/subtitles';\nimport { Header, HeaderMobile, ImageViewer, InfoBar, NavigationBar } from './components';\nimport { SWIPE_THRESHOLD } from './constants';\nimport { GalleryContext } from './context';\nimport { type GalleryImage, type ImageMeta } from './types';\n\nimport styles from './index.module.css';\n\nexport type GalleryProps = {\n /**\n * Управление видимостью\n */\n open: boolean;\n\n /**\n * Массив изображений\n */\n images: GalleryImage[];\n\n /**\n * Зациклить галерею\n * @default true\n */\n loop?: boolean;\n\n /**\n * Индекс открытого изображение\n * @default 0\n */\n initialSlide?: number;\n\n /**\n * Обработчик закрытия\n */\n onClose: () => void;\n\n /**\n * Индекс текущего изображения\n */\n slideIndex?: number;\n\n /**\n * Обработчик изменения текущего изображения\n */\n onSlideIndexChange?: (index: number) => void;\n\n /**\n * Дополнительный класс для попапа\n */\n popupClassName?: string;\n};\n\nconst DEFAULT_FULL_SCREEN = false;\nconst DEFAULT_MUTED_VIDEO = true;\nconst DEFAULT_PLAYING_VIDEO = true;\nconst DEFAULT_HIDE_NAVIGATION = false;\n\nconst Backdrop = () => null;\n\nexport const Gallery: FC<GalleryProps> = ({\n open,\n images,\n slideIndex,\n initialSlide = 0,\n loop = true,\n onClose,\n onSlideIndexChange,\n popupClassName,\n}) => {\n const currentSlideIndexState = useState(initialSlide);\n const uncontrolled = slideIndex === undefined;\n const [currentSlideIndex, setCurrentSlideIndex] = uncontrolled\n ? currentSlideIndexState\n : [slideIndex, onSlideIndexChange];\n\n const [swiper, setSwiper] = useState<SwiperCore>();\n const [imagesMeta, setImagesMeta] = useState<ImageMeta[]>([]);\n const [fullScreen, setFullScreen] = useState<boolean>(DEFAULT_FULL_SCREEN);\n const [mutedVideo, setMutedVideo] = useState<boolean>(DEFAULT_MUTED_VIDEO);\n const [playingVideo, setPlayingVideo] = useState<boolean>(DEFAULT_PLAYING_VIDEO);\n const [hideNavigation, setHideNavigation] = useState<boolean>(DEFAULT_HIDE_NAVIGATION);\n\n const isDesktop = useIsDesktop();\n\n const isCurrentVideo = !!imagesMeta[currentSlideIndex]?.player?.current;\n\n const bottomButton = images[currentSlideIndex]?.bottomButton;\n\n const slideTo = useCallback(\n (index: number) => {\n if (images[index]) {\n setCurrentSlideIndex?.(index);\n\n if (swiper) {\n setPlayingVideo(true);\n swiper.slideTo(index);\n }\n }\n },\n [images, setCurrentSlideIndex, swiper],\n );\n\n const slideNext = useCallback(() => {\n const lastIndex = images.length - 1;\n\n let nextIndex = currentSlideIndex + 1;\n\n if (nextIndex >= images.length) {\n nextIndex = loop ? 0 : lastIndex;\n }\n\n slideTo(nextIndex);\n }, [images.length, loop, currentSlideIndex, slideTo]);\n\n const slidePrev = useCallback(() => {\n const lastIndex = images.length - 1;\n\n let nextIndex = currentSlideIndex - 1;\n\n if (nextIndex < 0) {\n nextIndex = loop ? lastIndex : 0;\n }\n\n slideTo(nextIndex);\n }, [images.length, loop, currentSlideIndex, slideTo]);\n\n const setImageMeta = useCallback(\n (meta: ImageMeta, index: number) => {\n imagesMeta[index] = meta;\n\n setImagesMeta(imagesMeta.slice());\n },\n [imagesMeta],\n );\n\n const handleBottomButtonClick = useCallback(\n (e: MouseEvent) => {\n e.stopPropagation();\n if (bottomButton?.onClick) {\n bottomButton.onClick(e);\n }\n },\n [bottomButton],\n );\n\n const handleClose = useCallback(() => {\n onClose();\n\n if (uncontrolled) {\n setCurrentSlideIndex?.(initialSlide);\n }\n\n setFullScreen(false);\n }, [initialSlide, onClose, setCurrentSlideIndex, uncontrolled]);\n\n const handleEscapeKeyDown = () => {\n if (fullScreen) {\n setFullScreen(false);\n } else {\n handleClose();\n }\n };\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent) => {\n if (!open || fullScreen) {\n return;\n }\n\n switch (event.key) {\n case 'ArrowLeft':\n slidePrev();\n break;\n case 'ArrowRight':\n slideNext();\n break;\n }\n },\n [fullScreen, open, slideNext, slidePrev],\n );\n\n const onUnmount = useCallback(() => {\n setPlayingVideo(DEFAULT_PLAYING_VIDEO);\n setMutedVideo(DEFAULT_MUTED_VIDEO);\n }, [setPlayingVideo]);\n\n useEffect(() => {\n if (!uncontrolled && !swiper?.destroyed) {\n swiper?.slideTo(currentSlideIndex);\n }\n }, [uncontrolled, currentSlideIndex, swiper]);\n\n useEffect(() => {\n document.addEventListener('keydown', handleKeyDown);\n\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [handleKeyDown]);\n\n useEffect(() => {\n let startY: number;\n const abortController = new AbortController();\n const { signal } = abortController;\n\n document.addEventListener(\n 'touchstart',\n (e) => {\n startY = e.touches[0].clientY;\n },\n { signal },\n );\n\n document.addEventListener(\n 'touchmove',\n (e) => {\n const endY = e.changedTouches[0].clientY;\n const deltaY = startY - endY;\n\n // Если свайп вниз, закрываем галерею\n if (deltaY < SWIPE_THRESHOLD) {\n onClose();\n }\n },\n { signal },\n );\n\n return () => {\n abortController.abort();\n };\n }, [onClose]);\n\n const singleSlide = images.length === 1;\n\n const showNavigationBar = !singleSlide && !fullScreen;\n\n // eslint-disable-next-line react/jsx-no-constructed-context-values\n const galleryContext: GalleryContext = {\n view: isDesktop ? 'desktop' : 'mobile',\n singleSlide,\n currentSlideIndex,\n images,\n imagesMeta,\n fullScreen,\n initialSlide: uncontrolled ? initialSlide : currentSlideIndex,\n setFullScreen,\n playingVideo,\n setPlayingVideo,\n mutedVideo,\n setMutedVideo,\n hideNavigation,\n setHideNavigation,\n setImageMeta,\n slideNext,\n slidePrev,\n slideTo,\n getSwiper: () => swiper,\n setSwiper,\n onClose: handleClose,\n setCurrentSlideIndex,\n getCurrentImage: () => images[currentSlideIndex],\n getCurrentImageMeta: () => imagesMeta[currentSlideIndex],\n };\n\n return (\n <GalleryContext.Provider value={galleryContext}>\n <BaseModal\n open={open}\n className={cn(styles.modal, popupClassName)}\n onEscapeKeyDown={handleEscapeKeyDown}\n Backdrop={Backdrop}\n onUnmount={onUnmount}\n >\n <div\n className={cn(styles.container, {\n [styles.mobile]: !isDesktop,\n })}\n >\n {isDesktop ? <Header /> : <HeaderMobile />}\n {images.length === 1 ? <Single /> : <ImageViewer />}\n <nav\n className={cn({\n [styles.navigationVideo]: isCurrentVideo && !isDesktop,\n [styles.hide]: showNavigationBar && hideNavigation && !isDesktop,\n [styles.hideInfo]: !showNavigationBar && hideNavigation && !isDesktop,\n })}\n >\n {!isDesktop && <Subtitles />}\n {isCurrentVideo && !isDesktop && bottomButton && (\n <BottomButton\n bottomButton={bottomButton}\n onClick={handleBottomButtonClick}\n className={styles.bottomButton}\n />\n )}\n\n {showNavigationBar && <NavigationBar />}\n {!isDesktop && <InfoBar />}\n </nav>\n </div>\n </BaseModal>\n </GalleryContext.Provider>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Component.js","sources":["../src/Component.tsx"],"sourcesContent":["import React, { type FC, type MouseEvent, useCallback, useEffect, useState } from 'react';\nimport cn from 'classnames';\nimport type SwiperCore from 'swiper';\n\nimport { BaseModal } from '@alfalab/core-components-base-modal';\nimport { useIsDesktop } from '@alfalab/core-components-mq';\n\nimport { BottomButton } from './components/bottom-button';\nimport { Single } from './components/image-viewer/single';\nimport { Subtitles } from './components/subtitles';\nimport { Header, HeaderMobile, ImageViewer, InfoBar, NavigationBar } from './components';\nimport { SWIPE_THRESHOLD } from './constants';\nimport { GalleryContext } from './context';\nimport { type GalleryImage, type ImageMeta } from './types';\n\nimport styles from './index.module.css';\n\nexport type GalleryProps = {\n /**\n * Управление видимостью\n */\n open: boolean;\n\n /**\n * Массив изображений\n */\n images: GalleryImage[];\n\n /**\n * Зациклить галерею\n * @default true\n */\n loop?: boolean;\n\n /**\n * Индекс открытого изображение\n * @default 0\n */\n initialSlide?: number;\n\n /**\n * Обработчик закрытия\n */\n onClose: () => void;\n\n /**\n * Индекс текущего изображения\n */\n slideIndex?: number;\n\n /**\n * Обработчик изменения текущего изображения\n */\n onSlideIndexChange?: (index: number) => void;\n\n /**\n * Дополнительный класс для попапа\n */\n popupClassName?: string;\n};\n\nconst DEFAULT_FULL_SCREEN = false;\nconst DEFAULT_MUTED_VIDEO = true;\nconst DEFAULT_PLAYING_VIDEO = true;\nconst DEFAULT_HIDE_NAVIGATION = false;\n\nconst Backdrop = () => null;\n\nexport const Gallery: FC<GalleryProps> = ({\n open,\n images,\n slideIndex,\n initialSlide = 0,\n loop = true,\n onClose,\n onSlideIndexChange,\n popupClassName,\n}) => {\n const currentSlideIndexState = useState(initialSlide);\n const uncontrolled = slideIndex === undefined;\n const [currentSlideIndex, setCurrentSlideIndex] = uncontrolled\n ? currentSlideIndexState\n : [slideIndex, onSlideIndexChange];\n\n const [swiper, setSwiper] = useState<SwiperCore>();\n const [imagesMeta, setImagesMeta] = useState<ImageMeta[]>([]);\n const [fullScreen, setFullScreen] = useState<boolean>(DEFAULT_FULL_SCREEN);\n const [mutedVideo, setMutedVideo] = useState<boolean>(DEFAULT_MUTED_VIDEO);\n const [playingVideo, setPlayingVideo] = useState<boolean>(DEFAULT_PLAYING_VIDEO);\n const [hideNavigation, setHideNavigation] = useState<boolean>(DEFAULT_HIDE_NAVIGATION);\n\n const isDesktop = useIsDesktop();\n\n const isCurrentVideo = !!imagesMeta[currentSlideIndex]?.player?.current;\n\n const bottomButton = images[currentSlideIndex]?.bottomButton;\n\n const slideTo = useCallback(\n (index: number) => {\n if (images[index]) {\n setCurrentSlideIndex?.(index);\n\n if (swiper) {\n setPlayingVideo(true);\n swiper.slideTo(index);\n }\n }\n },\n [images, setCurrentSlideIndex, swiper],\n );\n\n const slideNext = useCallback(() => {\n const lastIndex = images.length - 1;\n\n let nextIndex = currentSlideIndex + 1;\n\n if (nextIndex >= images.length) {\n nextIndex = loop ? 0 : lastIndex;\n }\n\n slideTo(nextIndex);\n }, [images.length, loop, currentSlideIndex, slideTo]);\n\n const slidePrev = useCallback(() => {\n const lastIndex = images.length - 1;\n\n let nextIndex = currentSlideIndex - 1;\n\n if (nextIndex < 0) {\n nextIndex = loop ? lastIndex : 0;\n }\n\n slideTo(nextIndex);\n }, [images.length, loop, currentSlideIndex, slideTo]);\n\n const setImageMeta = useCallback((meta: ImageMeta, index: number) => {\n setImagesMeta((prevImagesMeta) => {\n const nextImagesMeta = prevImagesMeta.slice();\n\n nextImagesMeta[index] = meta;\n\n return nextImagesMeta;\n });\n }, []);\n\n const handleBottomButtonClick = useCallback(\n (e: MouseEvent) => {\n e.stopPropagation();\n if (bottomButton?.onClick) {\n bottomButton.onClick(e);\n }\n },\n [bottomButton],\n );\n\n const handleClose = useCallback(() => {\n onClose();\n\n if (uncontrolled) {\n setCurrentSlideIndex?.(initialSlide);\n }\n\n setFullScreen(false);\n }, [initialSlide, onClose, setCurrentSlideIndex, uncontrolled]);\n\n const handleEscapeKeyDown = () => {\n if (fullScreen) {\n setFullScreen(false);\n } else {\n handleClose();\n }\n };\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent) => {\n if (!open || fullScreen) {\n return;\n }\n\n switch (event.key) {\n case 'ArrowLeft':\n slidePrev();\n break;\n case 'ArrowRight':\n slideNext();\n break;\n }\n },\n [fullScreen, open, slideNext, slidePrev],\n );\n\n const onUnmount = useCallback(() => {\n setPlayingVideo(DEFAULT_PLAYING_VIDEO);\n setMutedVideo(DEFAULT_MUTED_VIDEO);\n }, [setPlayingVideo]);\n\n useEffect(() => {\n if (!uncontrolled && !swiper?.destroyed) {\n swiper?.slideTo(currentSlideIndex);\n }\n }, [uncontrolled, currentSlideIndex, swiper]);\n\n useEffect(() => {\n document.addEventListener('keydown', handleKeyDown);\n\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [handleKeyDown]);\n\n useEffect(() => {\n let startY: number;\n const abortController = new AbortController();\n const { signal } = abortController;\n\n document.addEventListener(\n 'touchstart',\n (e) => {\n startY = e.touches[0].clientY;\n },\n { signal },\n );\n\n document.addEventListener(\n 'touchmove',\n (e) => {\n const endY = e.changedTouches[0].clientY;\n const deltaY = startY - endY;\n\n // Если свайп вниз, закрываем галерею\n if (deltaY < SWIPE_THRESHOLD) {\n onClose();\n }\n },\n { signal },\n );\n\n return () => {\n abortController.abort();\n };\n }, [onClose]);\n\n const singleSlide = images.length === 1;\n\n const showNavigationBar = !singleSlide && !fullScreen;\n\n // eslint-disable-next-line react/jsx-no-constructed-context-values\n const galleryContext: GalleryContext = {\n view: isDesktop ? 'desktop' : 'mobile',\n singleSlide,\n currentSlideIndex,\n images,\n imagesMeta,\n fullScreen,\n initialSlide: uncontrolled ? initialSlide : currentSlideIndex,\n setFullScreen,\n playingVideo,\n setPlayingVideo,\n mutedVideo,\n setMutedVideo,\n hideNavigation,\n setHideNavigation,\n setImageMeta,\n slideNext,\n slidePrev,\n slideTo,\n getSwiper: () => swiper,\n setSwiper,\n onClose: handleClose,\n setCurrentSlideIndex,\n getCurrentImage: () => images[currentSlideIndex],\n getCurrentImageMeta: () => imagesMeta[currentSlideIndex],\n };\n\n return (\n <GalleryContext.Provider value={galleryContext}>\n <BaseModal\n open={open}\n className={cn(styles.modal, popupClassName)}\n onEscapeKeyDown={handleEscapeKeyDown}\n Backdrop={Backdrop}\n onUnmount={onUnmount}\n >\n <div\n className={cn(styles.container, {\n [styles.mobile]: !isDesktop,\n })}\n >\n {isDesktop ? <Header /> : <HeaderMobile />}\n {images.length === 1 ? <Single /> : <ImageViewer />}\n <nav\n className={cn({\n [styles.navigationVideo]: isCurrentVideo && !isDesktop,\n [styles.hide]: showNavigationBar && hideNavigation && !isDesktop,\n [styles.hideInfo]: !showNavigationBar && hideNavigation && !isDesktop,\n })}\n >\n {!isDesktop && <Subtitles />}\n {isCurrentVideo && !isDesktop && bottomButton && (\n <BottomButton\n bottomButton={bottomButton}\n onClick={handleBottomButtonClick}\n className={styles.bottomButton}\n />\n )}\n\n {showNavigationBar && <NavigationBar />}\n {!isDesktop && <InfoBar />}\n </nav>\n </div>\n </BaseModal>\n </GalleryContext.Provider>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@ import { useFocus } from '@alfalab/hooks';
6
6
  import { ChevronBackHeavyMIcon } from '@alfalab/icons-glyph/ChevronBackHeavyMIcon';
7
7
  import { ChevronForwardHeavyMIcon } from '@alfalab/icons-glyph/ChevronForwardHeavyMIcon';
8
8
  import { GalleryContext } from '../../context.js';
9
- import { isVideo, getImageAlt, getImageKey } from '../../utils/utils.js';
9
+ import { isVideo, getImageKey } from '../../utils/utils.js';
10
10
  import { TestIds } from '../../utils/constants.js';
11
11
  import { useHandleImageViewer } from './hooks.js';
12
12
  import { Slide } from './slide.js';
@@ -79,18 +79,26 @@ const ImageViewer = () => {
79
79
  [styles.focused]: leftArrowFocused,
80
80
  }), onClick: handlePrevClick, role: 'button', onKeyDown: handleArrowLeftKeyDown, tabIndex: 0, ref: leftArrowRef, "aria-label": '\u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0435\u0435 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435', "data-test-id": TestIds.PREV_SLIDE_BUTTON },
81
81
  React.createElement(ChevronBackHeavyMIcon, null))),
82
- fullScreen && !isVideo(currentImage?.src) && (React.createElement("img", { src: currentImage?.src, alt: currentImage ? getImageAlt(currentImage, currentSlideIndex) : '', className: styles.fullScreenImage })),
83
- React.createElement(Swiper, { ...swiperProps }, images.map((image, index) => {
84
- const meta = imagesMeta[index];
85
- const imageWidth = meta?.width || 1;
86
- const imageHeight = meta?.height || 1;
87
- const imageAspectRatio = imageWidth / imageHeight;
88
- const slideVisible = index === currentSlideIndex;
89
- return (React.createElement(SwiperSlide, { key: getImageKey(image, index), style: {
90
- pointerEvents: slideVisible ? 'auto' : 'none',
91
- transitionProperty: 'opacity',
92
- } }, ({ isActive }) => (React.createElement(Slide, { isActive: isActive, containerAspectRatio: swiperAspectRatio, image: image, containerHeight: swiperHeight, meta: meta, index: index, imageAspectRatio: imageAspectRatio, slideVisible: slideVisible }))));
93
- })),
82
+ fullScreen && currentImage && !isVideo(currentImage.src) && (React.createElement("div", { className: styles.fullScreenFrame },
83
+ React.createElement(Slide, { isActive: true, containerAspectRatio: swiperAspectRatio, image: currentImage, containerHeight: swiperHeight, meta: imagesMeta[currentSlideIndex], index: currentSlideIndex, imageAspectRatio: (imagesMeta[currentSlideIndex]?.width || 1) /
84
+ (imagesMeta[currentSlideIndex]?.height || 1), slideVisible: false, fullScreen: true }))),
85
+ React.createElement("div", { className: cn(styles.swiperFrame, {
86
+ [styles.mobile]: isMobile,
87
+ [styles.mobileVideo]: isMobile && isVideo(currentImage?.src),
88
+ [styles.fullScreenFrame]: fullScreen,
89
+ [styles.hiddenFrame]: fullScreen && !isVideo(currentImage?.src),
90
+ }) },
91
+ React.createElement(Swiper, { ...swiperProps }, images.map((image, index) => {
92
+ const meta = imagesMeta[index];
93
+ const imageWidth = meta?.width || 1;
94
+ const imageHeight = meta?.height || 1;
95
+ const imageAspectRatio = imageWidth / imageHeight;
96
+ const slideVisible = index === currentSlideIndex;
97
+ return (React.createElement(SwiperSlide, { key: getImageKey(image, index), style: {
98
+ pointerEvents: slideVisible ? 'auto' : 'none',
99
+ transitionProperty: 'opacity',
100
+ } }, ({ isActive }) => (React.createElement(Slide, { isActive: isActive, containerAspectRatio: swiperAspectRatio, image: image, containerHeight: swiperHeight, meta: meta, index: index, imageAspectRatio: imageAspectRatio, slideVisible: slideVisible, fullScreen: fullScreen && isVideo(image.src) }))));
101
+ }))),
94
102
  showControls && (React.createElement("div", { className: cn(styles.arrow, {
95
103
  [styles.focused]: rightArrowFocused,
96
104
  }), onClick: handleNextClick, role: 'button', onKeyDown: handleArrowRightKeyDown, tabIndex: 0, ref: rightArrowRef, "aria-label": '\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u0435 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435', "data-test-id": TestIds.NEXT_SLIDE_BUTTON },
@@ -1 +1 @@
1
- {"version":3,"file":"component.js","sources":["../../../src/components/image-viewer/component.tsx"],"sourcesContent":["import React, { type FC, type KeyboardEventHandler, useCallback, useContext, useMemo } from 'react';\nimport cn from 'classnames';\nimport { A11y, Controller } from 'swiper/modules';\nimport { Swiper, type SwiperProps, SwiperSlide } from 'swiper/react';\n\nimport { useFocus } from '@alfalab/hooks';\nimport { ChevronBackHeavyMIcon } from '@alfalab/icons-glyph/ChevronBackHeavyMIcon';\nimport { ChevronForwardHeavyMIcon } from '@alfalab/icons-glyph/ChevronForwardHeavyMIcon';\n\nimport { GalleryContext } from '../../context';\nimport { getImageAlt, getImageKey, isVideo, TestIds } from '../../utils';\n\nimport { useHandleImageViewer } from './hooks';\nimport { Slide } from './slide';\n\nimport styles from './index.module.css';\n\nexport const ImageViewer: FC = () => {\n const {\n images,\n imagesMeta,\n fullScreen,\n currentSlideIndex,\n initialSlide,\n setCurrentSlideIndex,\n getSwiper,\n setSwiper,\n slidePrev,\n slideNext,\n getCurrentImage,\n } = useContext(GalleryContext);\n\n const { handleWrapperClick, isMobile, rightArrowRef, leftArrowRef } = useHandleImageViewer();\n\n const [leftArrowFocused] = useFocus(leftArrowRef, 'keyboard');\n const [rightArrowFocused] = useFocus(rightArrowRef, 'keyboard');\n\n const swiper = getSwiper();\n const currentImage = getCurrentImage();\n\n const handleSlideChange = useCallback(() => {\n setCurrentSlideIndex?.(swiper?.activeIndex ?? initialSlide);\n }, [setCurrentSlideIndex, swiper, initialSlide]);\n\n const handlePrevClick = () => {\n slidePrev();\n };\n\n const handleNextClick = () => {\n slideNext();\n };\n\n const handleArrowLeftKeyDown: KeyboardEventHandler = (event) => {\n if (event.key === 'Enter') {\n slidePrev();\n }\n };\n\n const handleArrowRightKeyDown: KeyboardEventHandler = (event) => {\n if (event.key === 'Enter') {\n slideNext();\n }\n };\n\n const swiperProps = useMemo<SwiperProps>(\n () => ({\n slidesPerView: 1,\n effect: 'slide',\n className: cn(styles.swiper, {\n [styles.hidden]: fullScreen && !isVideo(currentImage?.src),\n [styles.fullScreenVideo]: fullScreen && isVideo(currentImage?.src),\n [styles.mobile]: isMobile,\n [styles.mobileVideo]: isMobile && isVideo(currentImage?.src),\n }),\n modules: [A11y, Controller],\n controller: { control: swiper },\n a11y: {\n slideRole: 'img',\n },\n initialSlide,\n simulateTouch: false,\n zoom: { maxRatio: 4, minRatio: 1, toggle: true },\n onSwiper: setSwiper,\n onSlideChange: handleSlideChange,\n lazy: { loadPrevNext: true },\n }),\n [\n fullScreen,\n currentImage?.src,\n isMobile,\n swiper,\n initialSlide,\n setSwiper,\n handleSlideChange,\n ],\n );\n\n const showControls = !fullScreen && !isMobile && !!images.length;\n\n const swiperWidth = swiper?.width || 1;\n const swiperHeight = swiper?.height || swiper?.width || 1;\n\n const swiperAspectRatio = swiperWidth / swiperHeight;\n\n return (\n <div\n className={cn(styles.component, {\n [styles.mobile]: isMobile,\n [styles.mobileVideo]: isMobile && isVideo(currentImage?.src),\n })}\n aria-hidden={true}\n onClick={handleWrapperClick}\n >\n {showControls && (\n <div\n className={cn(styles.arrow, {\n [styles.focused]: leftArrowFocused,\n })}\n onClick={handlePrevClick}\n role='button'\n onKeyDown={handleArrowLeftKeyDown}\n tabIndex={0}\n ref={leftArrowRef}\n aria-label='Предыдущее изображение'\n data-test-id={TestIds.PREV_SLIDE_BUTTON}\n >\n <ChevronBackHeavyMIcon />\n </div>\n )}\n\n {fullScreen && !isVideo(currentImage?.src) && (\n <img\n src={currentImage?.src}\n alt={currentImage ? getImageAlt(currentImage, currentSlideIndex) : ''}\n className={styles.fullScreenImage}\n />\n )}\n\n <Swiper {...swiperProps}>\n {images.map((image, index) => {\n const meta = imagesMeta[index];\n\n const imageWidth = meta?.width || 1;\n const imageHeight = meta?.height || 1;\n\n const imageAspectRatio = imageWidth / imageHeight;\n\n const slideVisible = index === currentSlideIndex;\n\n return (\n <SwiperSlide\n key={getImageKey(image, index)}\n style={{\n pointerEvents: slideVisible ? 'auto' : 'none',\n transitionProperty: 'opacity',\n }}\n >\n {({ isActive }) => (\n <Slide\n isActive={isActive}\n containerAspectRatio={swiperAspectRatio}\n image={image}\n containerHeight={swiperHeight}\n meta={meta}\n index={index}\n imageAspectRatio={imageAspectRatio}\n slideVisible={slideVisible}\n />\n )}\n </SwiperSlide>\n );\n })}\n </Swiper>\n\n {showControls && (\n <div\n className={cn(styles.arrow, {\n [styles.focused]: rightArrowFocused,\n })}\n onClick={handleNextClick}\n role='button'\n onKeyDown={handleArrowRightKeyDown}\n tabIndex={0}\n ref={rightArrowRef}\n aria-label='Следующее изображение'\n data-test-id={TestIds.NEXT_SLIDE_BUTTON}\n >\n <ChevronForwardHeavyMIcon />\n </div>\n )}\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"component.js","sources":["../../../src/components/image-viewer/component.tsx"],"sourcesContent":["import React, { type FC, type KeyboardEventHandler, useCallback, useContext, useMemo } from 'react';\nimport cn from 'classnames';\nimport { A11y, Controller } from 'swiper/modules';\nimport { Swiper, type SwiperProps, SwiperSlide } from 'swiper/react';\n\nimport { useFocus } from '@alfalab/hooks';\nimport { ChevronBackHeavyMIcon } from '@alfalab/icons-glyph/ChevronBackHeavyMIcon';\nimport { ChevronForwardHeavyMIcon } from '@alfalab/icons-glyph/ChevronForwardHeavyMIcon';\n\nimport { GalleryContext } from '../../context';\nimport { getImageKey, isVideo, TestIds } from '../../utils';\n\nimport { useHandleImageViewer } from './hooks';\nimport { Slide } from './slide';\n\nimport styles from './index.module.css';\n\nexport const ImageViewer: FC = () => {\n const {\n images,\n imagesMeta,\n fullScreen,\n currentSlideIndex,\n initialSlide,\n setCurrentSlideIndex,\n getSwiper,\n setSwiper,\n slidePrev,\n slideNext,\n getCurrentImage,\n } = useContext(GalleryContext);\n\n const { handleWrapperClick, isMobile, rightArrowRef, leftArrowRef } = useHandleImageViewer();\n\n const [leftArrowFocused] = useFocus(leftArrowRef, 'keyboard');\n const [rightArrowFocused] = useFocus(rightArrowRef, 'keyboard');\n\n const swiper = getSwiper();\n const currentImage = getCurrentImage();\n\n const handleSlideChange = useCallback(() => {\n setCurrentSlideIndex?.(swiper?.activeIndex ?? initialSlide);\n }, [setCurrentSlideIndex, swiper, initialSlide]);\n\n const handlePrevClick = () => {\n slidePrev();\n };\n\n const handleNextClick = () => {\n slideNext();\n };\n\n const handleArrowLeftKeyDown: KeyboardEventHandler = (event) => {\n if (event.key === 'Enter') {\n slidePrev();\n }\n };\n\n const handleArrowRightKeyDown: KeyboardEventHandler = (event) => {\n if (event.key === 'Enter') {\n slideNext();\n }\n };\n\n const swiperProps = useMemo<SwiperProps>(\n () => ({\n slidesPerView: 1,\n effect: 'slide',\n className: cn(styles.swiper, {\n [styles.hidden]: fullScreen && !isVideo(currentImage?.src),\n [styles.fullScreenVideo]: fullScreen && isVideo(currentImage?.src),\n [styles.mobile]: isMobile,\n [styles.mobileVideo]: isMobile && isVideo(currentImage?.src),\n }),\n modules: [A11y, Controller],\n controller: { control: swiper },\n a11y: {\n slideRole: 'img',\n },\n initialSlide,\n simulateTouch: false,\n zoom: { maxRatio: 4, minRatio: 1, toggle: true },\n onSwiper: setSwiper,\n onSlideChange: handleSlideChange,\n lazy: { loadPrevNext: true },\n }),\n [\n fullScreen,\n currentImage?.src,\n isMobile,\n swiper,\n initialSlide,\n setSwiper,\n handleSlideChange,\n ],\n );\n\n const showControls = !fullScreen && !isMobile && !!images.length;\n\n const swiperWidth = swiper?.width || 1;\n const swiperHeight = swiper?.height || swiper?.width || 1;\n\n const swiperAspectRatio = swiperWidth / swiperHeight;\n\n return (\n <div\n className={cn(styles.component, {\n [styles.mobile]: isMobile,\n [styles.mobileVideo]: isMobile && isVideo(currentImage?.src),\n })}\n aria-hidden={true}\n onClick={handleWrapperClick}\n >\n {showControls && (\n <div\n className={cn(styles.arrow, {\n [styles.focused]: leftArrowFocused,\n })}\n onClick={handlePrevClick}\n role='button'\n onKeyDown={handleArrowLeftKeyDown}\n tabIndex={0}\n ref={leftArrowRef}\n aria-label='Предыдущее изображение'\n data-test-id={TestIds.PREV_SLIDE_BUTTON}\n >\n <ChevronBackHeavyMIcon />\n </div>\n )}\n\n {fullScreen && currentImage && !isVideo(currentImage.src) && (\n <div className={styles.fullScreenFrame}>\n <Slide\n isActive={true}\n containerAspectRatio={swiperAspectRatio}\n image={currentImage}\n containerHeight={swiperHeight}\n meta={imagesMeta[currentSlideIndex]}\n index={currentSlideIndex}\n imageAspectRatio={\n (imagesMeta[currentSlideIndex]?.width || 1) /\n (imagesMeta[currentSlideIndex]?.height || 1)\n }\n slideVisible={false}\n fullScreen={true}\n />\n </div>\n )}\n\n <div\n className={cn(styles.swiperFrame, {\n [styles.mobile]: isMobile,\n [styles.mobileVideo]: isMobile && isVideo(currentImage?.src),\n [styles.fullScreenFrame]: fullScreen,\n [styles.hiddenFrame]: fullScreen && !isVideo(currentImage?.src),\n })}\n >\n <Swiper {...swiperProps}>\n {images.map((image, index) => {\n const meta = imagesMeta[index];\n\n const imageWidth = meta?.width || 1;\n const imageHeight = meta?.height || 1;\n\n const imageAspectRatio = imageWidth / imageHeight;\n\n const slideVisible = index === currentSlideIndex;\n\n return (\n <SwiperSlide\n key={getImageKey(image, index)}\n style={{\n pointerEvents: slideVisible ? 'auto' : 'none',\n transitionProperty: 'opacity',\n }}\n >\n {({ isActive }) => (\n <Slide\n isActive={isActive}\n containerAspectRatio={swiperAspectRatio}\n image={image}\n containerHeight={swiperHeight}\n meta={meta}\n index={index}\n imageAspectRatio={imageAspectRatio}\n slideVisible={slideVisible}\n fullScreen={fullScreen && isVideo(image.src)}\n />\n )}\n </SwiperSlide>\n );\n })}\n </Swiper>\n </div>\n\n {showControls && (\n <div\n className={cn(styles.arrow, {\n [styles.focused]: rightArrowFocused,\n })}\n onClick={handleNextClick}\n role='button'\n onKeyDown={handleArrowRightKeyDown}\n tabIndex={0}\n ref={rightArrowRef}\n aria-label='Следующее изображение'\n data-test-id={TestIds.NEXT_SLIDE_BUTTON}\n >\n <ChevronForwardHeavyMIcon />\n </div>\n )}\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;AAiBO,MAAM,WAAW,GAAO,MAAK;AAChC,IAAA,MAAM,EACF,MAAM,EACN,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,eAAe,GAClB,GAAG,UAAU,CAAC,cAAc,CAAC;AAE9B,IAAA,MAAM,EAAE,kBAAkB,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,oBAAoB,EAAE;IAE5F,MAAM,CAAC,gBAAgB,CAAC,GAAG,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC;IAC7D,MAAM,CAAC,iBAAiB,CAAC,GAAG,QAAQ,CAAC,aAAa,EAAE,UAAU,CAAC;AAE/D,IAAA,MAAM,MAAM,GAAG,SAAS,EAAE;AAC1B,IAAA,MAAM,YAAY,GAAG,eAAe,EAAE;AAEtC,IAAA,MAAM,iBAAiB,GAAG,WAAW,CAAC,MAAK;QACvC,oBAAoB,GAAG,MAAM,EAAE,WAAW,IAAI,YAAY,CAAC;KAC9D,EAAE,CAAC,oBAAoB,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;IAEhD,MAAM,eAAe,GAAG,MAAK;AACzB,QAAA,SAAS,EAAE;AACf,KAAC;IAED,MAAM,eAAe,GAAG,MAAK;AACzB,QAAA,SAAS,EAAE;AACf,KAAC;AAED,IAAA,MAAM,sBAAsB,GAAyB,CAAC,KAAK,KAAI;AAC3D,QAAA,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,EAAE;AACvB,YAAA,SAAS,EAAE;;AAEnB,KAAC;AAED,IAAA,MAAM,uBAAuB,GAAyB,CAAC,KAAK,KAAI;AAC5D,QAAA,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,EAAE;AACvB,YAAA,SAAS,EAAE;;AAEnB,KAAC;AAED,IAAA,MAAM,WAAW,GAAG,OAAO,CACvB,OAAO;AACH,QAAA,aAAa,EAAE,CAAC;AAChB,QAAA,MAAM,EAAE,OAAO;AACf,QAAA,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE;AACzB,YAAA,CAAC,MAAM,CAAC,MAAM,GAAG,UAAU,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC;AAC1D,YAAA,CAAC,MAAM,CAAC,eAAe,GAAG,UAAU,IAAI,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC;AAClE,YAAA,CAAC,MAAM,CAAC,MAAM,GAAG,QAAQ;AACzB,YAAA,CAAC,MAAM,CAAC,WAAW,GAAG,QAAQ,IAAI,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC;SAC/D,CAAC;AACF,QAAA,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC;AAC3B,QAAA,UAAU,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE;AAC/B,QAAA,IAAI,EAAE;AACF,YAAA,SAAS,EAAE,KAAK;AACnB,SAAA;QACD,YAAY;AACZ,QAAA,aAAa,EAAE,KAAK;AACpB,QAAA,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE;AAChD,QAAA,QAAQ,EAAE,SAAS;AACnB,QAAA,aAAa,EAAE,iBAAiB;AAChC,QAAA,IAAI,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;AAC/B,KAAA,CAAC,EACF;QACI,UAAU;AACV,QAAA,YAAY,EAAE,GAAG;QACjB,QAAQ;QACR,MAAM;QACN,YAAY;QACZ,SAAS;QACT,iBAAiB;AACpB,KAAA,CACJ;AAED,IAAA,MAAM,YAAY,GAAG,CAAC,UAAU,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM;AAEhE,IAAA,MAAM,WAAW,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IACtC,MAAM,YAAY,GAAG,MAAM,EAAE,MAAM,IAAI,MAAM,EAAE,KAAK,IAAI,CAAC;AAEzD,IAAA,MAAM,iBAAiB,GAAG,WAAW,GAAG,YAAY;IAEpD,QACI,6BACI,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE;AAC5B,YAAA,CAAC,MAAM,CAAC,MAAM,GAAG,QAAQ;AACzB,YAAA,CAAC,MAAM,CAAC,WAAW,GAAG,QAAQ,IAAI,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC;AAC/D,SAAA,CAAC,EACW,aAAA,EAAA,IAAI,EACjB,OAAO,EAAE,kBAAkB,EAAA;QAE1B,YAAY,KACT,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EACI,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE;AACxB,gBAAA,CAAC,MAAM,CAAC,OAAO,GAAG,gBAAgB;aACrC,CAAC,EACF,OAAO,EAAE,eAAe,EACxB,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,sBAAsB,EACjC,QAAQ,EAAE,CAAC,EACX,GAAG,EAAE,YAAY,EAAA,YAAA,EACN,iIAAwB,EAAA,cAAA,EACrB,OAAO,CAAC,iBAAiB,EAAA;YAEvC,KAAC,CAAA,aAAA,CAAA,qBAAqB,EAAG,IAAA,CAAA,CACvB,CACT;AAEA,QAAA,UAAU,IAAI,YAAY,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,KACrD,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,MAAM,CAAC,eAAe,EAAA;AAClC,YAAA,KAAA,CAAA,aAAA,CAAC,KAAK,EACF,EAAA,QAAQ,EAAE,IAAI,EACd,oBAAoB,EAAE,iBAAiB,EACvC,KAAK,EAAE,YAAY,EACnB,eAAe,EAAE,YAAY,EAC7B,IAAI,EAAE,UAAU,CAAC,iBAAiB,CAAC,EACnC,KAAK,EAAE,iBAAiB,EACxB,gBAAgB,EACZ,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,KAAK,IAAI,CAAC;AAC1C,qBAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,EAEhD,YAAY,EAAE,KAAK,EACnB,UAAU,EAAE,IAAI,EAAA,CAClB,CACA,CACT;AAED,QAAA,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EACI,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE;AAC9B,gBAAA,CAAC,MAAM,CAAC,MAAM,GAAG,QAAQ;AACzB,gBAAA,CAAC,MAAM,CAAC,WAAW,GAAG,QAAQ,IAAI,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC;AAC5D,gBAAA,CAAC,MAAM,CAAC,eAAe,GAAG,UAAU;AACpC,gBAAA,CAAC,MAAM,CAAC,WAAW,GAAG,UAAU,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC;aAClE,CAAC,EAAA;AAEF,YAAA,KAAA,CAAA,aAAA,CAAC,MAAM,EAAA,EAAA,GAAK,WAAW,EAAA,EAClB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAI;AACzB,gBAAA,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC;AAE9B,gBAAA,MAAM,UAAU,GAAG,IAAI,EAAE,KAAK,IAAI,CAAC;AACnC,gBAAA,MAAM,WAAW,GAAG,IAAI,EAAE,MAAM,IAAI,CAAC;AAErC,gBAAA,MAAM,gBAAgB,GAAG,UAAU,GAAG,WAAW;AAEjD,gBAAA,MAAM,YAAY,GAAG,KAAK,KAAK,iBAAiB;AAEhD,gBAAA,QACI,KAAA,CAAA,aAAA,CAAC,WAAW,EAAA,EACR,GAAG,EAAE,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,EAC9B,KAAK,EAAE;wBACH,aAAa,EAAE,YAAY,GAAG,MAAM,GAAG,MAAM;AAC7C,wBAAA,kBAAkB,EAAE,SAAS;qBAChC,EAEA,EAAA,CAAC,EAAE,QAAQ,EAAE,MACV,KAAA,CAAA,aAAA,CAAC,KAAK,EAAA,EACF,QAAQ,EAAE,QAAQ,EAClB,oBAAoB,EAAE,iBAAiB,EACvC,KAAK,EAAE,KAAK,EACZ,eAAe,EAAE,YAAY,EAC7B,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,gBAAgB,EAAE,gBAAgB,EAClC,YAAY,EAAE,YAAY,EAC1B,UAAU,EAAE,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAC9C,CAAA,CACL,CACS;aAErB,CAAC,CACG,CACP;QAEL,YAAY,KACT,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EACI,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE;AACxB,gBAAA,CAAC,MAAM,CAAC,OAAO,GAAG,iBAAiB;aACtC,CAAC,EACF,OAAO,EAAE,eAAe,EACxB,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,uBAAuB,EAClC,QAAQ,EAAE,CAAC,EACX,GAAG,EAAE,aAAa,EAAA,YAAA,EACP,2HAAuB,EAAA,cAAA,EACpB,OAAO,CAAC,iBAAiB,EAAA;AAEvC,YAAA,KAAA,CAAA,aAAA,CAAC,wBAAwB,EAAG,IAAA,CAAA,CAC1B,CACT,CACC;AAEd;;;;"}
@@ -4,6 +4,7 @@
4
4
  display: flex;
5
5
  flex-grow: 1;
6
6
  justify-content: center;
7
+ min-height: 0;
7
8
  background-color: var(--color-static-neutral-0-inverted);
8
9
  :global(.swiper) {
9
10
  margin-left: auto;
@@ -67,46 +68,80 @@
67
68
  z-index: -1000;
68
69
  }
69
70
 
70
- .swiper {
71
+ .swiperFrame {
71
72
  display: flex;
72
73
  width: 100%;
73
74
  height: 100%;
75
+ min-height: 0;
74
76
  max-height: calc(100vh - 168px);
77
+ max-height: calc(100dvh - 168px);
75
78
  padding: var(--gap-32) var(--gap-16);
76
79
  box-sizing: border-box;
77
80
  }
78
81
 
79
- .swiper.mobile {
82
+ .swiperFrame.mobile {
80
83
  max-height: calc(100vh - 210px);
84
+ max-height: calc(100dvh - 210px);
81
85
  }
82
86
 
83
- .swiper.mobileVideo {
87
+ .swiperFrame.mobileVideo {
84
88
  max-height: 100vh;
89
+ max-height: 100dvh;
85
90
  }
86
91
 
92
+ .fullScreenFrame {
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: center;
96
+ width: 100%;
97
+ height: 100%;
98
+ max-height: none;
99
+ min-height: 0;
100
+ padding: var(--gap-0);
101
+ box-sizing: border-box;
102
+ overflow: hidden;
103
+ }
104
+
105
+ .hiddenFrame {
106
+ flex: 0 0 0;
107
+ width: 0;
108
+ height: 0;
109
+ padding: var(--gap-0);
110
+ overflow: hidden;
111
+ }
112
+
113
+ .swiper {
114
+ width: 100%;
115
+ height: 100%;
116
+ }
117
+
118
+ .hidden {
119
+ display: none;
120
+ }
121
+
87
122
  .singleSlideContainer {
88
123
  display: flex;
89
124
  width: 100%;
90
125
  height: 100%;
126
+ min-height: 0;
91
127
 
92
128
  max-height: calc(100vh - 80px);
129
+ max-height: calc(100dvh - 80px);
93
130
  padding: var(--gap-32);
94
131
  box-sizing: border-box;
95
132
  }
96
133
 
97
134
  .singleSlideContainer.mobile {
98
135
  max-height: calc(100vh - 174px);
136
+ max-height: calc(100dvh - 174px);
99
137
  padding: 0;
100
138
  }
101
139
 
102
140
  .singleSlideContainer.mobileVideo {
103
141
  max-height: 100vh;
142
+ max-height: 100dvh;
104
143
  }
105
144
 
106
- .hidden {
107
- display: none;
108
- }
109
-
110
145
  .slide {
111
146
  position: relative;
112
147
  display: flex;
@@ -127,8 +162,12 @@
127
162
  }
128
163
 
129
164
  .image {
130
- width: 0;
131
- height: 0;
165
+ width: auto;
166
+ height: auto;
167
+ max-width: 100%;
168
+ max-height: 100%;
169
+ -o-object-fit: contain;
170
+ object-fit: contain;
132
171
  -webkit-user-select: none;
133
172
  -moz-user-select: none;
134
173
  user-select: none;
@@ -143,6 +182,10 @@
143
182
  position: relative;
144
183
  width: auto;
145
184
  height: auto;
185
+ max-width: 100%;
186
+ max-height: 100%;
187
+ -o-object-fit: contain;
188
+ object-fit: contain;
146
189
  -webkit-user-select: none;
147
190
  -moz-user-select: none;
148
191
  user-select: none;
@@ -158,6 +201,16 @@
158
201
  height: auto;
159
202
  }
160
203
 
204
+ .fullScreenMedia {
205
+ width: 100%;
206
+ height: 100%;
207
+ max-width: 100%;
208
+ max-height: 100%;
209
+ -o-object-fit: contain;
210
+ object-fit: contain;
211
+ border-radius: var(--border-radius-0);
212
+ }
213
+
161
214
  .arrow {
162
215
  display: flex;
163
216
  flex-direction: column;
@@ -210,14 +263,9 @@
210
263
  margin-bottom: var(--gap-4);
211
264
  }
212
265
 
213
- .fullScreenImage {
214
- width: 100%;
215
- height: auto;
216
- background-color: var(--color-light-base-bg-primary);
217
- }
218
-
219
266
  .fullScreenVideo {
220
- width: calc(100% - 192px);
221
- max-height: calc(100vh - 82px);
267
+ width: 100%;
268
+ height: 100%;
269
+ max-height: none;
222
270
  }
223
271
  }
@@ -1,7 +1,7 @@
1
1
  import React, { useContext, useRef } from 'react';
2
2
  import cn from 'classnames';
3
3
  import { GalleryContext } from '../../context.js';
4
- import { isVideo, getImageAlt } from '../../utils/utils.js';
4
+ import { isVideo } from '../../utils/utils.js';
5
5
  import { useHandleImageViewer } from './hooks.js';
6
6
  import { Slide } from './slide.js';
7
7
  import styles from './index.module.css';
@@ -21,7 +21,8 @@ const Single = () => {
21
21
  const wrapperAspectRatio = (wrapperRect?.width || 1) / (wrapperRect?.height || 1);
22
22
  return (
23
23
  /* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */
24
- React.createElement("div", { className: styles.component, onClick: handleWrapperClick }, fullScreen && !isVideo(currentImage?.src) ? (React.createElement("img", { src: currentImage?.src, alt: currentImage ? getImageAlt(currentImage, currentSlideIndex) : '', className: styles.fullScreenImage })) : (React.createElement("div", { className: cn(styles.singleSlideContainer, {
24
+ React.createElement("div", { className: styles.component, onClick: handleWrapperClick }, fullScreen && !isVideo(currentImage?.src) ? (React.createElement("div", { className: styles.fullScreenFrame },
25
+ React.createElement(Slide, { isActive: true, containerAspectRatio: wrapperAspectRatio, image: currentImage, containerHeight: wrapperRect?.height || 0, meta: currentImageMeta, index: currentSlideIndex, imageAspectRatio: imageAspectRatio, slideVisible: false, fullScreen: true }))) : (React.createElement("div", { className: cn(styles.singleSlideContainer, {
25
26
  [styles.mobile]: isMobile,
26
27
  [styles.mobileVideo]: isMobile && isVideo(currentImage?.src),
27
28
  }), ref: wrapperRef },
@@ -1 +1 @@
1
- {"version":3,"file":"single.js","sources":["../../../src/components/image-viewer/single.tsx"],"sourcesContent":["import React, { type FC, useContext, useRef } from 'react';\nimport cn from 'classnames';\n\nimport { GalleryContext } from '../../context';\nimport { getImageAlt, isVideo } from '../../utils';\n\nimport { useHandleImageViewer } from './hooks';\nimport { Slide } from './slide';\n\nimport styles from './index.module.css';\n\nexport const Single: FC = () => {\n const { fullScreen, currentSlideIndex, getCurrentImage, getCurrentImageMeta } =\n useContext(GalleryContext);\n\n const { handleWrapperClick, isMobile } = useHandleImageViewer();\n\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n const currentImage = getCurrentImage();\n const currentImageMeta = getCurrentImageMeta();\n\n if (!currentImage) return null;\n\n const imageWidth = currentImageMeta?.width || 1;\n const imageHeight = currentImageMeta?.height || 1;\n\n const imageAspectRatio = imageWidth / imageHeight;\n\n const wrapperRect = wrapperRef.current?.getBoundingClientRect();\n\n const wrapperAspectRatio = (wrapperRect?.width || 1) / (wrapperRect?.height || 1);\n\n return (\n /* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */\n <div className={styles.component} onClick={handleWrapperClick}>\n {fullScreen && !isVideo(currentImage?.src) ? (\n <img\n src={currentImage?.src}\n alt={currentImage ? getImageAlt(currentImage, currentSlideIndex) : ''}\n className={styles.fullScreenImage}\n />\n ) : (\n <div\n className={cn(styles.singleSlideContainer, {\n [styles.mobile]: isMobile,\n [styles.mobileVideo]: isMobile && isVideo(currentImage?.src),\n })}\n ref={wrapperRef}\n >\n <Slide\n isActive={true}\n containerAspectRatio={wrapperAspectRatio}\n image={currentImage}\n containerHeight={wrapperRect?.height || 0}\n meta={currentImageMeta}\n index={currentSlideIndex}\n imageAspectRatio={imageAspectRatio}\n slideVisible={true}\n />\n </div>\n )}\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAWO,MAAM,MAAM,GAAO,MAAK;AAC3B,IAAA,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,eAAe,EAAE,mBAAmB,EAAE,GACzE,UAAU,CAAC,cAAc,CAAC;IAE9B,MAAM,EAAE,kBAAkB,EAAE,QAAQ,EAAE,GAAG,oBAAoB,EAAE;AAE/D,IAAA,MAAM,UAAU,GAAG,MAAM,CAAiB,IAAI,CAAC;AAE/C,IAAA,MAAM,YAAY,GAAG,eAAe,EAAE;AACtC,IAAA,MAAM,gBAAgB,GAAG,mBAAmB,EAAE;AAE9C,IAAA,IAAI,CAAC,YAAY;AAAE,QAAA,OAAO,IAAI;AAE9B,IAAA,MAAM,UAAU,GAAG,gBAAgB,EAAE,KAAK,IAAI,CAAC;AAC/C,IAAA,MAAM,WAAW,GAAG,gBAAgB,EAAE,MAAM,IAAI,CAAC;AAEjD,IAAA,MAAM,gBAAgB,GAAG,UAAU,GAAG,WAAW;IAEjD,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,EAAE,qBAAqB,EAAE;AAE/D,IAAA,MAAM,kBAAkB,GAAG,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,KAAK,WAAW,EAAE,MAAM,IAAI,CAAC,CAAC;IAEjF;;AAEI,IAAA,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,kBAAkB,EAAA,EACxD,UAAU,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,IACtC,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EACI,GAAG,EAAE,YAAY,EAAE,GAAG,EACtB,GAAG,EAAE,YAAY,GAAG,WAAW,CAAC,YAAY,EAAE,iBAAiB,CAAC,GAAG,EAAE,EACrE,SAAS,EAAE,MAAM,CAAC,eAAe,EACnC,CAAA,KAEF,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EACI,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,oBAAoB,EAAE;AACvC,YAAA,CAAC,MAAM,CAAC,MAAM,GAAG,QAAQ;AACzB,YAAA,CAAC,MAAM,CAAC,WAAW,GAAG,QAAQ,IAAI,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC;SAC/D,CAAC,EACF,GAAG,EAAE,UAAU,EAAA;AAEf,QAAA,KAAA,CAAA,aAAA,CAAC,KAAK,EACF,EAAA,QAAQ,EAAE,IAAI,EACd,oBAAoB,EAAE,kBAAkB,EACxC,KAAK,EAAE,YAAY,EACnB,eAAe,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC,EACzC,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,iBAAiB,EACxB,gBAAgB,EAAE,gBAAgB,EAClC,YAAY,EAAE,IAAI,EAAA,CACpB,CACA,CACT,CACC;AAEd;;;;"}
1
+ {"version":3,"file":"single.js","sources":["../../../src/components/image-viewer/single.tsx"],"sourcesContent":["import React, { type FC, useContext, useRef } from 'react';\nimport cn from 'classnames';\n\nimport { GalleryContext } from '../../context';\nimport { isVideo } from '../../utils';\n\nimport { useHandleImageViewer } from './hooks';\nimport { Slide } from './slide';\n\nimport styles from './index.module.css';\n\nexport const Single: FC = () => {\n const { fullScreen, currentSlideIndex, getCurrentImage, getCurrentImageMeta } =\n useContext(GalleryContext);\n\n const { handleWrapperClick, isMobile } = useHandleImageViewer();\n\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n const currentImage = getCurrentImage();\n const currentImageMeta = getCurrentImageMeta();\n\n if (!currentImage) return null;\n\n const imageWidth = currentImageMeta?.width || 1;\n const imageHeight = currentImageMeta?.height || 1;\n\n const imageAspectRatio = imageWidth / imageHeight;\n\n const wrapperRect = wrapperRef.current?.getBoundingClientRect();\n\n const wrapperAspectRatio = (wrapperRect?.width || 1) / (wrapperRect?.height || 1);\n\n return (\n /* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */\n <div className={styles.component} onClick={handleWrapperClick}>\n {fullScreen && !isVideo(currentImage?.src) ? (\n <div className={styles.fullScreenFrame}>\n <Slide\n isActive={true}\n containerAspectRatio={wrapperAspectRatio}\n image={currentImage}\n containerHeight={wrapperRect?.height || 0}\n meta={currentImageMeta}\n index={currentSlideIndex}\n imageAspectRatio={imageAspectRatio}\n slideVisible={false}\n fullScreen={true}\n />\n </div>\n ) : (\n <div\n className={cn(styles.singleSlideContainer, {\n [styles.mobile]: isMobile,\n [styles.mobileVideo]: isMobile && isVideo(currentImage?.src),\n })}\n ref={wrapperRef}\n >\n <Slide\n isActive={true}\n containerAspectRatio={wrapperAspectRatio}\n image={currentImage}\n containerHeight={wrapperRect?.height || 0}\n meta={currentImageMeta}\n index={currentSlideIndex}\n imageAspectRatio={imageAspectRatio}\n slideVisible={true}\n />\n </div>\n )}\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAWO,MAAM,MAAM,GAAO,MAAK;AAC3B,IAAA,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,eAAe,EAAE,mBAAmB,EAAE,GACzE,UAAU,CAAC,cAAc,CAAC;IAE9B,MAAM,EAAE,kBAAkB,EAAE,QAAQ,EAAE,GAAG,oBAAoB,EAAE;AAE/D,IAAA,MAAM,UAAU,GAAG,MAAM,CAAiB,IAAI,CAAC;AAE/C,IAAA,MAAM,YAAY,GAAG,eAAe,EAAE;AACtC,IAAA,MAAM,gBAAgB,GAAG,mBAAmB,EAAE;AAE9C,IAAA,IAAI,CAAC,YAAY;AAAE,QAAA,OAAO,IAAI;AAE9B,IAAA,MAAM,UAAU,GAAG,gBAAgB,EAAE,KAAK,IAAI,CAAC;AAC/C,IAAA,MAAM,WAAW,GAAG,gBAAgB,EAAE,MAAM,IAAI,CAAC;AAEjD,IAAA,MAAM,gBAAgB,GAAG,UAAU,GAAG,WAAW;IAEjD,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,EAAE,qBAAqB,EAAE;AAE/D,IAAA,MAAM,kBAAkB,GAAG,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,KAAK,WAAW,EAAE,MAAM,IAAI,CAAC,CAAC;IAEjF;;AAEI,IAAA,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,kBAAkB,EAAA,EACxD,UAAU,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,IACtC,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,MAAM,CAAC,eAAe,EAAA;QAClC,KAAC,CAAA,aAAA,CAAA,KAAK,EACF,EAAA,QAAQ,EAAE,IAAI,EACd,oBAAoB,EAAE,kBAAkB,EACxC,KAAK,EAAE,YAAY,EACnB,eAAe,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC,EACzC,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,iBAAiB,EACxB,gBAAgB,EAAE,gBAAgB,EAClC,YAAY,EAAE,KAAK,EACnB,UAAU,EAAE,IAAI,EAClB,CAAA,CACA,KAEN,KACI,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,oBAAoB,EAAE;AACvC,YAAA,CAAC,MAAM,CAAC,MAAM,GAAG,QAAQ;AACzB,YAAA,CAAC,MAAM,CAAC,WAAW,GAAG,QAAQ,IAAI,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC;SAC/D,CAAC,EACF,GAAG,EAAE,UAAU,EAAA;AAEf,QAAA,KAAA,CAAA,aAAA,CAAC,KAAK,EACF,EAAA,QAAQ,EAAE,IAAI,EACd,oBAAoB,EAAE,kBAAkB,EACxC,KAAK,EAAE,YAAY,EACnB,eAAe,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC,EACzC,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,iBAAiB,EACxB,gBAAgB,EAAE,gBAAgB,EAClC,YAAY,EAAE,IAAI,EAAA,CACpB,CACA,CACT,CACC;AAEd;;;;"}
@@ -9,6 +9,7 @@ type SlideProps = {
9
9
  index: number;
10
10
  containerHeight: number;
11
11
  slideVisible: boolean;
12
+ fullScreen?: boolean;
12
13
  };
13
14
  export declare const Slide: FC<SlideProps>;
14
15
  export {};
@@ -1,4 +1,4 @@
1
- import React, { useContext } from 'react';
1
+ import React, { useContext, useCallback } from 'react';
2
2
  import cn from 'classnames';
3
3
  import { Spinner } from '@alfalab/core-components-spinner/moderncssm';
4
4
  import { TypographyText } from '@alfalab/core-components-typography/moderncssm';
@@ -24,27 +24,31 @@ const SlideInner = ({ children, broken, loading, isVideoView }) => {
24
24
  broken ? React.createElement("div", { className: styles.placeholder }, content) : content,
25
25
  React.createElement(Spinner, { className: styles.spinner, preset: 48, visible: loading })));
26
26
  };
27
- const Slide = ({ isActive, meta, containerAspectRatio, imageAspectRatio, image, index, containerHeight, slideVisible, }) => {
27
+ const Slide = ({ isActive, meta, containerAspectRatio, imageAspectRatio, image, index, containerHeight, slideVisible, fullScreen, }) => {
28
28
  const { view } = useContext(GalleryContext);
29
29
  const { handleLoad, handleLoadError } = useHandleImageViewer();
30
30
  const broken = Boolean(meta?.broken);
31
31
  const small = isSmallImage(meta);
32
32
  const verticalImageFit = !small && containerAspectRatio > imageAspectRatio;
33
33
  const horizontalImageFit = !small && containerAspectRatio <= imageAspectRatio;
34
+ const handleImageRef = useCallback((node) => {
35
+ if (node?.complete && node.naturalWidth > 0 && !meta) {
36
+ handleLoad({ currentTarget: node }, index);
37
+ }
38
+ }, [handleLoad, index, meta]);
34
39
  if (isVideo(image.src)) {
35
40
  return (React.createElement(SlideInner, { isVideoView: true, active: isActive, broken: broken, loading: !meta },
36
- React.createElement(Video, { url: image.src, index: index, isActive: isActive })));
41
+ React.createElement(Video, { url: image.src, index: index, isActive: isActive, className: cn({ [styles.fullScreenMedia]: fullScreen }) })));
37
42
  }
38
43
  return (React.createElement(SlideInner, { active: isActive, broken: broken, loading: !meta },
39
- React.createElement("img", { src: image.src, alt: getImageAlt(image, index), className: cn({
44
+ React.createElement("img", { ref: handleImageRef, src: image.src, alt: getImageAlt(image, index), className: cn({
40
45
  [styles.smallImage]: small,
41
46
  [styles.image]: !small && meta,
42
47
  [styles.mobile]: view === 'mobile',
48
+ [styles.fullScreenMedia]: fullScreen,
43
49
  [styles.verticalImageFit]: verticalImageFit,
44
50
  [styles.horizontalImageFit]: horizontalImageFit,
45
- }), onLoad: (event) => handleLoad(event, index), onError: () => handleLoadError(index), style: {
46
- maxHeight: `${containerHeight}px`,
47
- }, "data-test-id": slideVisible ? TestIds.ACTIVE_IMAGE : undefined })));
51
+ }), onLoad: (event) => handleLoad(event, index), onError: () => handleLoadError(index), style: fullScreen ? undefined : { maxHeight: `${containerHeight}px` }, "data-test-id": slideVisible ? TestIds.ACTIVE_IMAGE : undefined })));
48
52
  };
49
53
 
50
54
  export { Slide };