@alfalab/core-components-gallery 7.2.3 → 7.3.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.
- package/Component.js +51 -7
- package/Component.js.map +1 -1
- package/components/bottom-button/index.css +5 -5
- package/components/bottom-button/index.module.css.js +1 -1
- package/components/buttons/index.css +5 -5
- package/components/buttons/index.d.ts +3 -1
- package/components/buttons/index.js +49 -12
- package/components/buttons/index.js.map +1 -1
- package/components/buttons/index.module.css.js +1 -1
- package/components/header/Component.js +1 -0
- package/components/header/Component.js.map +1 -1
- package/components/header/index.css +3 -2
- package/components/header/index.module.css.js +1 -1
- package/components/header/index.module.css.js.map +1 -1
- package/components/header-info-block/Component.js +2 -1
- package/components/header-info-block/Component.js.map +1 -1
- package/components/header-info-block/index.css +4 -4
- package/components/header-info-block/index.module.css.js +1 -1
- package/components/header-mobile/index.css +6 -6
- package/components/header-mobile/index.module.css.js +1 -1
- package/components/image-preview/Component.js +2 -1
- package/components/image-preview/Component.js.map +1 -1
- package/components/image-preview/index.css +20 -20
- package/components/image-preview/index.module.css.js +1 -1
- package/components/image-preview/index.module.css.js.map +1 -1
- package/components/image-viewer/hooks.js +3 -2
- package/components/image-viewer/hooks.js.map +1 -1
- package/components/image-viewer/index.css +30 -31
- package/components/image-viewer/index.module.css.js +1 -1
- package/components/image-viewer/index.module.css.js.map +1 -1
- package/components/image-viewer/single.js +1 -0
- package/components/image-viewer/single.js.map +1 -1
- package/components/image-viewer/slide.js +3 -2
- package/components/image-viewer/slide.js.map +1 -1
- package/components/image-viewer/video/index.css +22 -10
- package/components/image-viewer/video/index.js +50 -15
- package/components/image-viewer/video/index.js.map +1 -1
- package/components/image-viewer/video/index.module.css.js +1 -1
- package/components/image-viewer/video/index.module.css.js.map +1 -1
- package/components/info-bar/Component.js +1 -0
- package/components/info-bar/Component.js.map +1 -1
- package/components/info-bar/index.css +3 -3
- package/components/info-bar/index.module.css.js +1 -1
- package/components/navigation-bar/Component.js +56 -26
- package/components/navigation-bar/Component.js.map +1 -1
- package/components/navigation-bar/index.css +21 -11
- package/components/navigation-bar/index.module.css.js +1 -1
- package/components/navigation-bar/index.module.css.js.map +1 -1
- package/components/subtitles/index.css +3 -3
- package/components/subtitles/index.module.css.js +1 -1
- package/constants.d.ts +1 -1
- package/constants.js +1 -1
- package/constants.js.map +1 -1
- package/cssm/Component.js +51 -7
- package/cssm/Component.js.map +1 -1
- package/cssm/components/buttons/index.d.ts +3 -1
- package/cssm/components/buttons/index.js +54 -17
- package/cssm/components/buttons/index.js.map +1 -1
- package/cssm/components/header/Component.js +1 -0
- package/cssm/components/header/Component.js.map +1 -1
- package/cssm/components/header/index.module.css +2 -1
- package/cssm/components/header-info-block/Component.js +2 -1
- package/cssm/components/header-info-block/Component.js.map +1 -1
- package/cssm/components/image-preview/Component.js +2 -1
- package/cssm/components/image-preview/Component.js.map +1 -1
- package/cssm/components/image-preview/index.module.css +3 -3
- package/cssm/components/image-viewer/hooks.js +3 -2
- package/cssm/components/image-viewer/hooks.js.map +1 -1
- package/cssm/components/image-viewer/index.module.css +2 -3
- package/cssm/components/image-viewer/single.js +1 -0
- package/cssm/components/image-viewer/single.js.map +1 -1
- package/cssm/components/image-viewer/slide.js +3 -2
- package/cssm/components/image-viewer/slide.js.map +1 -1
- package/cssm/components/image-viewer/video/index.js +50 -15
- package/cssm/components/image-viewer/video/index.js.map +1 -1
- package/cssm/components/image-viewer/video/index.module.css +15 -3
- package/cssm/components/info-bar/Component.js +1 -0
- package/cssm/components/info-bar/Component.js.map +1 -1
- package/cssm/components/navigation-bar/Component.js +56 -26
- package/cssm/components/navigation-bar/Component.js.map +1 -1
- package/cssm/components/navigation-bar/index.module.css +13 -3
- package/cssm/constants.d.ts +1 -1
- package/cssm/constants.js +1 -1
- package/cssm/constants.js.map +1 -1
- package/cssm/hooks/use-custom-subtitles.js +57 -11
- package/cssm/hooks/use-custom-subtitles.js.map +1 -1
- package/cssm/index.js +1 -0
- package/cssm/index.js.map +1 -1
- package/cssm/types.d.ts +4 -2
- package/cssm/utils/index.d.ts +1 -0
- package/cssm/utils/index.js +2 -0
- package/cssm/utils/index.js.map +1 -1
- package/cssm/utils/modern-download.d.ts +6 -0
- package/cssm/utils/modern-download.js +113 -0
- package/cssm/utils/modern-download.js.map +1 -0
- package/esm/Component.js +51 -7
- package/esm/Component.js.map +1 -1
- package/esm/components/bottom-button/index.css +5 -5
- package/esm/components/bottom-button/index.module.css.js +1 -1
- package/esm/components/buttons/index.css +5 -5
- package/esm/components/buttons/index.d.ts +3 -1
- package/esm/components/buttons/index.js +50 -13
- package/esm/components/buttons/index.js.map +1 -1
- package/esm/components/buttons/index.module.css.js +1 -1
- package/esm/components/header/Component.js +1 -0
- package/esm/components/header/Component.js.map +1 -1
- package/esm/components/header/index.css +3 -2
- package/esm/components/header/index.module.css.js +1 -1
- package/esm/components/header/index.module.css.js.map +1 -1
- package/esm/components/header-info-block/Component.js +2 -1
- package/esm/components/header-info-block/Component.js.map +1 -1
- package/esm/components/header-info-block/index.css +4 -4
- package/esm/components/header-info-block/index.module.css.js +1 -1
- package/esm/components/header-mobile/index.css +6 -6
- package/esm/components/header-mobile/index.module.css.js +1 -1
- package/esm/components/image-preview/Component.js +2 -1
- package/esm/components/image-preview/Component.js.map +1 -1
- package/esm/components/image-preview/index.css +20 -20
- package/esm/components/image-preview/index.module.css.js +1 -1
- package/esm/components/image-preview/index.module.css.js.map +1 -1
- package/esm/components/image-viewer/hooks.js +3 -2
- package/esm/components/image-viewer/hooks.js.map +1 -1
- package/esm/components/image-viewer/index.css +30 -31
- package/esm/components/image-viewer/index.module.css.js +1 -1
- package/esm/components/image-viewer/index.module.css.js.map +1 -1
- package/esm/components/image-viewer/single.js +1 -0
- package/esm/components/image-viewer/single.js.map +1 -1
- package/esm/components/image-viewer/slide.js +3 -2
- package/esm/components/image-viewer/slide.js.map +1 -1
- package/esm/components/image-viewer/video/index.css +22 -10
- package/esm/components/image-viewer/video/index.js +51 -16
- package/esm/components/image-viewer/video/index.js.map +1 -1
- package/esm/components/image-viewer/video/index.module.css.js +1 -1
- package/esm/components/image-viewer/video/index.module.css.js.map +1 -1
- package/esm/components/info-bar/Component.js +1 -0
- package/esm/components/info-bar/Component.js.map +1 -1
- package/esm/components/info-bar/index.css +3 -3
- package/esm/components/info-bar/index.module.css.js +1 -1
- package/esm/components/navigation-bar/Component.js +56 -25
- package/esm/components/navigation-bar/Component.js.map +1 -1
- package/esm/components/navigation-bar/index.css +21 -11
- package/esm/components/navigation-bar/index.module.css.js +1 -1
- package/esm/components/navigation-bar/index.module.css.js.map +1 -1
- package/esm/components/subtitles/index.css +3 -3
- package/esm/components/subtitles/index.module.css.js +1 -1
- package/esm/constants.d.ts +1 -1
- package/esm/constants.js +1 -1
- package/esm/constants.js.map +1 -1
- package/esm/hooks/use-custom-subtitles.js +57 -11
- package/esm/hooks/use-custom-subtitles.js.map +1 -1
- package/esm/index.css +9 -9
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/index.module.css.js +1 -1
- package/esm/types.d.ts +4 -2
- package/esm/utils/index.d.ts +1 -0
- package/esm/utils/index.js +1 -0
- package/esm/utils/index.js.map +1 -1
- package/esm/utils/modern-download.d.ts +6 -0
- package/esm/utils/modern-download.js +109 -0
- package/esm/utils/modern-download.js.map +1 -0
- package/hooks/use-custom-subtitles.js +57 -11
- package/hooks/use-custom-subtitles.js.map +1 -1
- package/index.css +9 -9
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/index.module.css.js +1 -1
- package/modern/Component.js +50 -7
- package/modern/Component.js.map +1 -1
- package/modern/components/bottom-button/index.css +5 -5
- package/modern/components/bottom-button/index.module.css.js +1 -1
- package/modern/components/buttons/index.css +5 -5
- package/modern/components/buttons/index.d.ts +3 -1
- package/modern/components/buttons/index.js +51 -12
- package/modern/components/buttons/index.js.map +1 -1
- package/modern/components/buttons/index.module.css.js +1 -1
- package/modern/components/header/index.css +3 -2
- package/modern/components/header/index.module.css.js +1 -1
- package/modern/components/header/index.module.css.js.map +1 -1
- package/modern/components/header-info-block/Component.js +1 -1
- package/modern/components/header-info-block/Component.js.map +1 -1
- package/modern/components/header-info-block/index.css +4 -4
- package/modern/components/header-info-block/index.module.css.js +1 -1
- package/modern/components/header-mobile/index.css +6 -6
- package/modern/components/header-mobile/index.module.css.js +1 -1
- package/modern/components/image-preview/Component.js +1 -1
- package/modern/components/image-preview/Component.js.map +1 -1
- package/modern/components/image-preview/index.css +20 -20
- package/modern/components/image-preview/index.module.css.js +1 -1
- package/modern/components/image-preview/index.module.css.js.map +1 -1
- package/modern/components/image-viewer/hooks.js +3 -2
- package/modern/components/image-viewer/hooks.js.map +1 -1
- package/modern/components/image-viewer/index.css +30 -31
- package/modern/components/image-viewer/index.module.css.js +1 -1
- package/modern/components/image-viewer/index.module.css.js.map +1 -1
- package/modern/components/image-viewer/slide.js +2 -2
- package/modern/components/image-viewer/slide.js.map +1 -1
- package/modern/components/image-viewer/video/index.css +22 -10
- package/modern/components/image-viewer/video/index.js +47 -12
- package/modern/components/image-viewer/video/index.js.map +1 -1
- package/modern/components/image-viewer/video/index.module.css.js +1 -1
- package/modern/components/image-viewer/video/index.module.css.js.map +1 -1
- package/modern/components/info-bar/index.css +3 -3
- package/modern/components/info-bar/index.module.css.js +1 -1
- package/modern/components/navigation-bar/Component.js +55 -25
- package/modern/components/navigation-bar/Component.js.map +1 -1
- package/modern/components/navigation-bar/index.css +21 -11
- package/modern/components/navigation-bar/index.module.css.js +1 -1
- package/modern/components/navigation-bar/index.module.css.js.map +1 -1
- package/modern/components/subtitles/index.css +3 -3
- package/modern/components/subtitles/index.module.css.js +1 -1
- package/modern/constants.d.ts +1 -1
- package/modern/constants.js +1 -1
- package/modern/constants.js.map +1 -1
- package/modern/hooks/use-custom-subtitles.js +56 -9
- package/modern/hooks/use-custom-subtitles.js.map +1 -1
- package/modern/index.css +9 -9
- package/modern/index.module.css.js +1 -1
- package/modern/types.d.ts +4 -2
- package/modern/utils/index.d.ts +1 -0
- package/modern/utils/index.js +1 -0
- package/modern/utils/index.js.map +1 -1
- package/modern/utils/modern-download.d.ts +6 -0
- package/modern/utils/modern-download.js +76 -0
- package/modern/utils/modern-download.js.map +1 -0
- package/moderncssm/Component.js +50 -7
- package/moderncssm/Component.js.map +1 -1
- package/moderncssm/components/buttons/index.d.ts +3 -1
- package/moderncssm/components/buttons/index.js +51 -12
- package/moderncssm/components/buttons/index.js.map +1 -1
- package/moderncssm/components/header/index.module.css +1 -1
- package/moderncssm/components/header-info-block/Component.js +1 -1
- package/moderncssm/components/header-info-block/Component.js.map +1 -1
- package/moderncssm/components/image-preview/Component.js +1 -1
- package/moderncssm/components/image-preview/Component.js.map +1 -1
- package/moderncssm/components/image-preview/index.module.css +2 -2
- package/moderncssm/components/image-viewer/hooks.js +3 -2
- package/moderncssm/components/image-viewer/hooks.js.map +1 -1
- package/moderncssm/components/image-viewer/index.module.css +2 -2
- package/moderncssm/components/image-viewer/slide.js +2 -2
- package/moderncssm/components/image-viewer/slide.js.map +1 -1
- package/moderncssm/components/image-viewer/video/index.js +47 -12
- package/moderncssm/components/image-viewer/video/index.js.map +1 -1
- package/moderncssm/components/image-viewer/video/index.module.css +16 -3
- package/moderncssm/components/navigation-bar/Component.js +55 -25
- package/moderncssm/components/navigation-bar/Component.js.map +1 -1
- package/moderncssm/components/navigation-bar/index.module.css +14 -2
- package/moderncssm/constants.d.ts +1 -1
- package/moderncssm/constants.js +1 -1
- package/moderncssm/constants.js.map +1 -1
- package/moderncssm/hooks/use-custom-subtitles.js +56 -9
- package/moderncssm/hooks/use-custom-subtitles.js.map +1 -1
- package/moderncssm/types.d.ts +4 -2
- package/moderncssm/utils/index.d.ts +1 -0
- package/moderncssm/utils/index.js +1 -0
- package/moderncssm/utils/index.js.map +1 -1
- package/moderncssm/utils/modern-download.d.ts +6 -0
- package/moderncssm/utils/modern-download.js +76 -0
- package/moderncssm/utils/modern-download.js.map +1 -0
- package/package.json +12 -12
- package/src/Component.tsx +63 -6
- package/src/components/buttons/index.tsx +157 -62
- package/src/components/header/index.module.css +1 -1
- package/src/components/header-info-block/Component.tsx +2 -2
- package/src/components/image-preview/Component.tsx +1 -1
- package/src/components/image-preview/index.module.css +2 -2
- package/src/components/image-viewer/hooks.ts +3 -2
- package/src/components/image-viewer/index.module.css +2 -2
- package/src/components/image-viewer/slide.tsx +2 -1
- package/src/components/image-viewer/video/index.module.css +16 -3
- package/src/components/image-viewer/video/index.tsx +62 -13
- package/src/components/navigation-bar/Component.tsx +68 -27
- package/src/components/navigation-bar/index.module.css +12 -2
- package/src/constants.ts +1 -1
- package/src/hooks/use-custom-subtitles.ts +72 -12
- package/src/types.ts +4 -2
- package/src/utils/index.ts +1 -0
- package/src/utils/modern-download.ts +107 -0
- package/types.d.ts +4 -2
- package/utils/index.d.ts +1 -0
- package/utils/index.js +2 -0
- package/utils/index.js.map +1 -1
- package/utils/modern-download.d.ts +6 -0
- package/utils/modern-download.js +113 -0
- package/utils/modern-download.js.map +1 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useRef, useState, useContext, useCallback, useEffect } from 'react';
|
|
2
2
|
import cn from 'classnames';
|
|
3
|
-
import
|
|
3
|
+
import { isClient } from '@alfalab/core-components-shared/moderncssm';
|
|
4
4
|
import { GalleryContext } from '../../context.js';
|
|
5
5
|
import { getImageKey } from '../../utils/utils.js';
|
|
6
6
|
import { TestIds } from '../../utils/constants.js';
|
|
@@ -8,11 +8,13 @@ import { ImagePreview } from '../image-preview/Component.js';
|
|
|
8
8
|
import styles from './index.module.css';
|
|
9
9
|
|
|
10
10
|
const MIN_SCROLL_STEP = 24;
|
|
11
|
-
const
|
|
12
|
-
const SCROLL_THRESHOLD = 150; // Расстояние от границы, при котором начинается прокрутка
|
|
11
|
+
const DRAG_CLICK_THRESHOLD = 5;
|
|
13
12
|
const NavigationBar = () => {
|
|
14
13
|
const containerRef = useRef(null);
|
|
15
|
-
const
|
|
14
|
+
const dragStartXRef = useRef(0);
|
|
15
|
+
const dragStartScrollLeftRef = useRef(0);
|
|
16
|
+
const suppressClickRef = useRef(false);
|
|
17
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
16
18
|
const { images, currentSlideIndex, setCurrentSlideIndex, getSwiper, setPlayingVideo, view } = useContext(GalleryContext);
|
|
17
19
|
const swiper = getSwiper();
|
|
18
20
|
const handlePreviewSelect = (index) => {
|
|
@@ -31,32 +33,57 @@ const NavigationBar = () => {
|
|
|
31
33
|
});
|
|
32
34
|
}
|
|
33
35
|
}, []);
|
|
34
|
-
const handlePreviewMouseDown = () => {
|
|
35
|
-
|
|
36
|
+
const handlePreviewMouseDown = (e) => {
|
|
37
|
+
if (e.button !== 0 || !containerRef.current) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
dragStartXRef.current = e.clientX;
|
|
41
|
+
dragStartScrollLeftRef.current = containerRef.current.scrollLeft;
|
|
42
|
+
suppressClickRef.current = false;
|
|
43
|
+
setIsDragging(true);
|
|
36
44
|
};
|
|
37
|
-
const handlePreviewMouseUp = () => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
const handlePreviewMouseUp = useCallback(() => {
|
|
46
|
+
setIsDragging(false);
|
|
47
|
+
}, []);
|
|
48
|
+
const dragTo = useCallback((clientX) => {
|
|
49
|
+
const container = containerRef.current;
|
|
50
|
+
if (!container) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const deltaX = clientX - dragStartXRef.current;
|
|
54
|
+
if (Math.abs(deltaX) > DRAG_CLICK_THRESHOLD) {
|
|
55
|
+
suppressClickRef.current = true;
|
|
41
56
|
}
|
|
57
|
+
container.scrollLeft = dragStartScrollLeftRef.current - deltaX;
|
|
58
|
+
}, []);
|
|
59
|
+
const handleMouseNavigationMove = (e) => {
|
|
60
|
+
if (!isDragging) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
dragTo(e.clientX);
|
|
42
64
|
};
|
|
43
|
-
const
|
|
44
|
-
if (!
|
|
65
|
+
const handleClickCapture = (e) => {
|
|
66
|
+
if (!suppressClickRef.current) {
|
|
45
67
|
return;
|
|
46
|
-
const container = containerRef.current;
|
|
47
|
-
const { width: containerWidth, left: containerLeft } = container.getBoundingClientRect();
|
|
48
|
-
const mouseX = e.clientX;
|
|
49
|
-
// Если курсор близко к правой границе
|
|
50
|
-
if (mouseX > containerWidth + containerLeft - SCROLL_THRESHOLD) {
|
|
51
|
-
const scrollValue = (mouseX - (containerWidth + containerLeft - SCROLL_THRESHOLD)) * SCROLL_SPEED;
|
|
52
|
-
container.scrollBy({ left: scrollValue, behavior: 'smooth' });
|
|
53
68
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
e.stopPropagation();
|
|
71
|
+
suppressClickRef.current = false;
|
|
72
|
+
};
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (!isClient() || !isDragging) {
|
|
75
|
+
return undefined;
|
|
58
76
|
}
|
|
59
|
-
|
|
77
|
+
const handleDocumentMouseMove = (event) => {
|
|
78
|
+
dragTo(event.clientX);
|
|
79
|
+
};
|
|
80
|
+
document.addEventListener('mousemove', handleDocumentMouseMove);
|
|
81
|
+
document.addEventListener('mouseup', handlePreviewMouseUp);
|
|
82
|
+
return () => {
|
|
83
|
+
document.removeEventListener('mousemove', handleDocumentMouseMove);
|
|
84
|
+
document.removeEventListener('mouseup', handlePreviewMouseUp);
|
|
85
|
+
};
|
|
86
|
+
}, [dragTo, handlePreviewMouseUp, isDragging]);
|
|
60
87
|
const handlePreviewPosition = useCallback((preview, containerWidth) => {
|
|
61
88
|
const { right, left, x } = preview.getBoundingClientRect();
|
|
62
89
|
if (view === 'mobile') {
|
|
@@ -82,7 +109,10 @@ const NavigationBar = () => {
|
|
|
82
109
|
}, [currentSlideIndex, handlePreviewPosition, scroll]);
|
|
83
110
|
return (
|
|
84
111
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
85
|
-
React.createElement("div", { className: cn(styles.component, {
|
|
112
|
+
React.createElement("div", { className: cn(styles.component, {
|
|
113
|
+
[styles.mobile]: view === 'mobile',
|
|
114
|
+
[styles.dragging]: isDragging,
|
|
115
|
+
}), ref: containerRef, "data-test-id": TestIds.NAVIGATION_BAR, onMouseDown: handlePreviewMouseDown, onMouseUp: handlePreviewMouseUp, onMouseMove: handleMouseNavigationMove, onClickCapture: handleClickCapture }, images.map((image, index) => {
|
|
86
116
|
const active = index === currentSlideIndex;
|
|
87
117
|
return (React.createElement(ImagePreview, { key: getImageKey(image, index), image: image, active: active, index: index, onSelect: handlePreviewSelect, className: cn(styles.preview, { [styles.mobile]: view === 'mobile' }) }));
|
|
88
118
|
})));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Component.js","sources":["../../../src/components/navigation-bar/Component.tsx"],"sourcesContent":["import React, { type FC, useCallback, useContext, useEffect, useRef, useState } from 'react';\nimport cn from 'classnames';\nimport
|
|
1
|
+
{"version":3,"file":"Component.js","sources":["../../../src/components/navigation-bar/Component.tsx"],"sourcesContent":["import React, { type FC, useCallback, useContext, useEffect, useRef, useState } from 'react';\nimport cn from 'classnames';\n\nimport { isClient } from '@alfalab/core-components-shared';\n\nimport { GalleryContext } from '../../context';\nimport { getImageKey, TestIds } from '../../utils';\nimport { ImagePreview } from '../image-preview';\n\nimport styles from './index.module.css';\n\nconst MIN_SCROLL_STEP = 24;\nconst DRAG_CLICK_THRESHOLD = 5;\n\nexport const NavigationBar: FC = () => {\n const containerRef = useRef<HTMLDivElement>(null);\n const dragStartXRef = useRef<number>(0);\n const dragStartScrollLeftRef = useRef<number>(0);\n const suppressClickRef = useRef<boolean>(false);\n\n const [isDragging, setIsDragging] = useState<boolean>(false);\n\n const { images, currentSlideIndex, setCurrentSlideIndex, getSwiper, setPlayingVideo, view } =\n useContext(GalleryContext);\n\n const swiper = getSwiper();\n\n const handlePreviewSelect = (index: number) => {\n setCurrentSlideIndex?.(index);\n\n if (swiper) {\n setPlayingVideo(true);\n swiper.slideTo(index);\n }\n };\n\n const scroll = useCallback((scrollValue: number) => {\n if (containerRef.current) {\n containerRef.current.scroll({\n top: 0,\n left: containerRef.current.scrollLeft + scrollValue,\n behavior: 'smooth',\n });\n }\n }, []);\n\n const handlePreviewMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {\n if (e.button !== 0 || !containerRef.current) {\n return;\n }\n\n dragStartXRef.current = e.clientX;\n dragStartScrollLeftRef.current = containerRef.current.scrollLeft;\n suppressClickRef.current = false;\n setIsDragging(true);\n };\n\n const handlePreviewMouseUp = useCallback(() => {\n setIsDragging(false);\n }, []);\n\n const dragTo = useCallback((clientX: number) => {\n const container = containerRef.current;\n\n if (!container) {\n return;\n }\n\n const deltaX = clientX - dragStartXRef.current;\n\n if (Math.abs(deltaX) > DRAG_CLICK_THRESHOLD) {\n suppressClickRef.current = true;\n }\n\n container.scrollLeft = dragStartScrollLeftRef.current - deltaX;\n }, []);\n\n const handleMouseNavigationMove = (e: React.MouseEvent<HTMLDivElement>) => {\n if (!isDragging) {\n return;\n }\n\n dragTo(e.clientX);\n };\n\n const handleClickCapture = (e: React.MouseEvent<HTMLDivElement>) => {\n if (!suppressClickRef.current) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n suppressClickRef.current = false;\n };\n\n useEffect(() => {\n if (!isClient() || !isDragging) {\n return undefined;\n }\n\n const handleDocumentMouseMove = (event: MouseEvent) => {\n dragTo(event.clientX);\n };\n\n document.addEventListener('mousemove', handleDocumentMouseMove);\n document.addEventListener('mouseup', handlePreviewMouseUp);\n\n return () => {\n document.removeEventListener('mousemove', handleDocumentMouseMove);\n document.removeEventListener('mouseup', handlePreviewMouseUp);\n };\n }, [dragTo, handlePreviewMouseUp, isDragging]);\n\n const handlePreviewPosition = useCallback(\n (preview: Element, containerWidth: number) => {\n const { right, left, x } = preview.getBoundingClientRect();\n\n if (view === 'mobile') {\n scroll(x - containerWidth / 2 + MIN_SCROLL_STEP); // Передвигаем в центр активное превью\n }\n\n if (right > containerWidth) {\n const scrollValue = right - containerWidth + MIN_SCROLL_STEP;\n\n scroll(scrollValue);\n } else if (left < 0) {\n const scrollValue = left - MIN_SCROLL_STEP;\n\n scroll(scrollValue);\n }\n },\n [scroll, view],\n );\n\n useEffect(() => {\n if (containerRef.current) {\n const { width: containerWidth } = containerRef.current.getBoundingClientRect();\n\n const activePreview = containerRef.current.children[currentSlideIndex];\n\n if (activePreview) {\n handlePreviewPosition(activePreview, containerWidth);\n }\n }\n }, [currentSlideIndex, handlePreviewPosition, scroll]);\n\n return (\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <div\n className={cn(styles.component, {\n [styles.mobile]: view === 'mobile',\n [styles.dragging]: isDragging,\n })}\n ref={containerRef}\n data-test-id={TestIds.NAVIGATION_BAR}\n onMouseDown={handlePreviewMouseDown}\n onMouseUp={handlePreviewMouseUp}\n onMouseMove={handleMouseNavigationMove}\n onClickCapture={handleClickCapture}\n >\n {images.map((image, index) => {\n const active = index === currentSlideIndex;\n\n return (\n <ImagePreview\n key={getImageKey(image, index)}\n image={image}\n active={active}\n index={index}\n onSelect={handlePreviewSelect}\n className={cn(styles.preview, { [styles.mobile]: view === 'mobile' })}\n />\n );\n })}\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -8,15 +8,27 @@
|
|
|
8
8
|
flex-shrink: 0;
|
|
9
9
|
overflow-x: auto;
|
|
10
10
|
box-sizing: border-box;
|
|
11
|
-
padding: var(--gap-12) var(--gap-
|
|
11
|
+
padding: var(--gap-12) var(--gap-32);
|
|
12
12
|
scrollbar-width: none;
|
|
13
13
|
background-color: var(--color-static-neutral-0-inverted);
|
|
14
|
+
cursor: grab;
|
|
15
|
+
-webkit-user-select: none;
|
|
16
|
+
-moz-user-select: none;
|
|
17
|
+
user-select: none;
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
.component.mobile {
|
|
17
|
-
padding: var(--gap-8)
|
|
21
|
+
padding: var(--gap-8);
|
|
18
22
|
}
|
|
19
23
|
|
|
24
|
+
.component.dragging {
|
|
25
|
+
cursor: grabbing;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.component.dragging * {
|
|
29
|
+
cursor: grabbing;
|
|
30
|
+
}
|
|
31
|
+
|
|
20
32
|
.component::-webkit-scrollbar {
|
|
21
33
|
display: none;
|
|
22
34
|
}
|
package/moderncssm/constants.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sources":["../src/constants.ts"],"sourcesContent":["export const SWIPE_THRESHOLD =
|
|
1
|
+
{"version":3,"file":"constants.js","sources":["../src/constants.ts"],"sourcesContent":["export const SWIPE_THRESHOLD = 250;\n\nexport const PREVIEW_WIDTH_MOBILE = 46;\nexport const PREVIEW_HEIGHT_MOBILE = 46;\n\nexport const PREVIEW_WIDTH_DESKTOP = 56;\nexport const PREVIEW_HEIGHT_DESKTOP = 56;\n\nexport const PREVIEW_VIDEO_MULTIPLIER = 12;\n"],"names":[],"mappings":"AAAO,MAAM,eAAe,GAAG;AAExB,MAAM,oBAAoB,GAAG;AAC7B,MAAM,qBAAqB,GAAG;AAE9B,MAAM,qBAAqB,GAAG;AAC9B,MAAM,sBAAsB,GAAG;AAE/B,MAAM,wBAAwB,GAAG;;;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useContext, useState, useEffect } from 'react';
|
|
2
2
|
import { GalleryContext } from '../context.js';
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const SUBTITLES_FADE_DURATION_SECONDS = 0.5;
|
|
5
5
|
const useCustomSubtitles = () => {
|
|
6
6
|
const { getCurrentImageMeta } = useContext(GalleryContext);
|
|
7
7
|
const meta = getCurrentImageMeta();
|
|
@@ -9,23 +9,70 @@ const useCustomSubtitles = () => {
|
|
|
9
9
|
const [currentSub, setCurrentSub] = useState('');
|
|
10
10
|
const player = meta?.player?.current;
|
|
11
11
|
useEffect(() => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
if (!player) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
const { textTracks } = player;
|
|
16
|
+
let textTrack;
|
|
17
|
+
let hideTimeoutId;
|
|
18
|
+
const clearHideTimeout = () => {
|
|
19
|
+
if (hideTimeoutId !== undefined) {
|
|
20
|
+
clearTimeout(hideTimeoutId);
|
|
21
|
+
hideTimeoutId = undefined;
|
|
15
22
|
}
|
|
16
|
-
|
|
23
|
+
};
|
|
24
|
+
const syncSubtitles = () => {
|
|
25
|
+
clearHideTimeout();
|
|
17
26
|
const activeCue = textTrack?.activeCues?.[0];
|
|
18
27
|
if (!activeCue?.text) {
|
|
19
28
|
setShowSub(false);
|
|
20
29
|
return;
|
|
21
30
|
}
|
|
22
|
-
const
|
|
23
|
-
|
|
31
|
+
const fadeStartTime = activeCue.endTime - SUBTITLES_FADE_DURATION_SECONDS;
|
|
32
|
+
const isVisible = player.currentTime <= fadeStartTime;
|
|
24
33
|
setCurrentSub(activeCue.text);
|
|
25
34
|
setShowSub(isVisible);
|
|
26
|
-
|
|
35
|
+
if (!isVisible || player.paused || player.playbackRate <= 0) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const timeUntilFadeMs = ((fadeStartTime - player.currentTime) / player.playbackRate) * 1000;
|
|
39
|
+
hideTimeoutId = setTimeout(() => {
|
|
40
|
+
setShowSub(false);
|
|
41
|
+
}, timeUntilFadeMs);
|
|
42
|
+
};
|
|
43
|
+
const connectTextTrack = () => {
|
|
44
|
+
const nextTextTrack = Array.from(textTracks).find((track) => track.kind === 'subtitles');
|
|
45
|
+
if (nextTextTrack === textTrack) {
|
|
46
|
+
syncSubtitles();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
textTrack?.removeEventListener('cuechange', syncSubtitles);
|
|
50
|
+
textTrack = nextTextTrack;
|
|
51
|
+
textTrack?.addEventListener('cuechange', syncSubtitles);
|
|
52
|
+
syncSubtitles();
|
|
53
|
+
};
|
|
54
|
+
player.addEventListener('play', syncSubtitles);
|
|
55
|
+
player.addEventListener('playing', syncSubtitles);
|
|
56
|
+
player.addEventListener('pause', clearHideTimeout);
|
|
57
|
+
player.addEventListener('waiting', clearHideTimeout);
|
|
58
|
+
player.addEventListener('seeking', clearHideTimeout);
|
|
59
|
+
player.addEventListener('seeked', syncSubtitles);
|
|
60
|
+
player.addEventListener('ratechange', syncSubtitles);
|
|
61
|
+
textTracks.addEventListener('addtrack', connectTextTrack);
|
|
62
|
+
textTracks.addEventListener('change', connectTextTrack);
|
|
63
|
+
connectTextTrack();
|
|
27
64
|
return () => {
|
|
28
|
-
|
|
65
|
+
clearHideTimeout();
|
|
66
|
+
textTrack?.removeEventListener('cuechange', syncSubtitles);
|
|
67
|
+
player.removeEventListener('play', syncSubtitles);
|
|
68
|
+
player.removeEventListener('playing', syncSubtitles);
|
|
69
|
+
player.removeEventListener('pause', clearHideTimeout);
|
|
70
|
+
player.removeEventListener('waiting', clearHideTimeout);
|
|
71
|
+
player.removeEventListener('seeking', clearHideTimeout);
|
|
72
|
+
player.removeEventListener('seeked', syncSubtitles);
|
|
73
|
+
player.removeEventListener('ratechange', syncSubtitles);
|
|
74
|
+
textTracks.removeEventListener('addtrack', connectTextTrack);
|
|
75
|
+
textTracks.removeEventListener('change', connectTextTrack);
|
|
29
76
|
};
|
|
30
77
|
}, [player]);
|
|
31
78
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-custom-subtitles.js","sources":["../../src/hooks/use-custom-subtitles.ts"],"sourcesContent":["import { useContext, useEffect, useState } from 'react';\n\nimport { GalleryContext } from '../context';\n\nconst
|
|
1
|
+
{"version":3,"file":"use-custom-subtitles.js","sources":["../../src/hooks/use-custom-subtitles.ts"],"sourcesContent":["import { useContext, useEffect, useState } from 'react';\n\nimport { GalleryContext } from '../context';\n\nconst SUBTITLES_FADE_DURATION_SECONDS = 0.5;\n\nexport const useCustomSubtitles = () => {\n const { getCurrentImageMeta } = useContext(GalleryContext);\n\n const meta = getCurrentImageMeta();\n\n const [showSub, setShowSub] = useState(false);\n const [currentSub, setCurrentSub] = useState('');\n\n const player = meta?.player?.current;\n\n useEffect(() => {\n if (!player) {\n return undefined;\n }\n\n const { textTracks } = player;\n\n let textTrack: TextTrack | undefined;\n let hideTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n const clearHideTimeout = () => {\n if (hideTimeoutId !== undefined) {\n clearTimeout(hideTimeoutId);\n hideTimeoutId = undefined;\n }\n };\n\n const syncSubtitles = () => {\n clearHideTimeout();\n\n const activeCue = textTrack?.activeCues?.[0] as VTTCue | undefined;\n\n if (!activeCue?.text) {\n setShowSub(false);\n\n return;\n }\n\n const fadeStartTime = activeCue.endTime - SUBTITLES_FADE_DURATION_SECONDS;\n const isVisible = player.currentTime <= fadeStartTime;\n\n setCurrentSub(activeCue.text);\n setShowSub(isVisible);\n\n if (!isVisible || player.paused || player.playbackRate <= 0) {\n return;\n }\n\n const timeUntilFadeMs =\n ((fadeStartTime - player.currentTime) / player.playbackRate) * 1000;\n\n hideTimeoutId = setTimeout(() => {\n setShowSub(false);\n }, timeUntilFadeMs);\n };\n\n const connectTextTrack = () => {\n const nextTextTrack = Array.from(textTracks).find(\n (track) => track.kind === 'subtitles',\n );\n\n if (nextTextTrack === textTrack) {\n syncSubtitles();\n\n return;\n }\n\n textTrack?.removeEventListener('cuechange', syncSubtitles);\n textTrack = nextTextTrack;\n textTrack?.addEventListener('cuechange', syncSubtitles);\n syncSubtitles();\n };\n\n player.addEventListener('play', syncSubtitles);\n player.addEventListener('playing', syncSubtitles);\n player.addEventListener('pause', clearHideTimeout);\n player.addEventListener('waiting', clearHideTimeout);\n player.addEventListener('seeking', clearHideTimeout);\n player.addEventListener('seeked', syncSubtitles);\n player.addEventListener('ratechange', syncSubtitles);\n textTracks.addEventListener('addtrack', connectTextTrack);\n textTracks.addEventListener('change', connectTextTrack);\n\n connectTextTrack();\n\n return () => {\n clearHideTimeout();\n textTrack?.removeEventListener('cuechange', syncSubtitles);\n player.removeEventListener('play', syncSubtitles);\n player.removeEventListener('playing', syncSubtitles);\n player.removeEventListener('pause', clearHideTimeout);\n player.removeEventListener('waiting', clearHideTimeout);\n player.removeEventListener('seeking', clearHideTimeout);\n player.removeEventListener('seeked', syncSubtitles);\n player.removeEventListener('ratechange', syncSubtitles);\n textTracks.removeEventListener('addtrack', connectTextTrack);\n textTracks.removeEventListener('change', connectTextTrack);\n };\n }, [player]);\n\n return {\n showSub,\n currentSub,\n };\n};\n"],"names":[],"mappings":"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"}
|
package/moderncssm/types.d.ts
CHANGED
|
@@ -40,9 +40,11 @@ export type ImageMeta = {
|
|
|
40
40
|
height: number;
|
|
41
41
|
broken?: boolean;
|
|
42
42
|
player?: never;
|
|
43
|
+
loaded?: boolean;
|
|
43
44
|
} | {
|
|
44
|
-
width?:
|
|
45
|
-
height?:
|
|
45
|
+
width?: number;
|
|
46
|
+
height?: number;
|
|
46
47
|
broken?: boolean;
|
|
47
48
|
player: RefObject<HTMLVideoElement>;
|
|
49
|
+
loaded?: boolean;
|
|
48
50
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { splitFilename } from './split-filename.js';
|
|
2
2
|
export { PLACEHOLDER_HEIGHT, PLACEHOLDER_WIDTH, getImageAlt, getImageKey, isSmallImage, isVideo } from './utils.js';
|
|
3
3
|
export { TestIds } from './constants.js';
|
|
4
|
+
export { downloadFile } from './modern-download.js';
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const downloadWithBlob = (blob, fileName) => {
|
|
2
|
+
const url = URL.createObjectURL(blob);
|
|
3
|
+
const link = document.createElement('a');
|
|
4
|
+
link.href = url;
|
|
5
|
+
link.download = fileName;
|
|
6
|
+
document.body.appendChild(link);
|
|
7
|
+
link.click();
|
|
8
|
+
document.body.removeChild(link);
|
|
9
|
+
setTimeout(() => URL.revokeObjectURL(url), 100);
|
|
10
|
+
};
|
|
11
|
+
const downloadWithLink = (url, fileName) => {
|
|
12
|
+
const link = document.createElement('a');
|
|
13
|
+
link.href = url;
|
|
14
|
+
link.download = fileName;
|
|
15
|
+
link.target = '_blank';
|
|
16
|
+
link.rel = 'noopener noreferrer';
|
|
17
|
+
document.body.appendChild(link);
|
|
18
|
+
link.click();
|
|
19
|
+
document.body.removeChild(link);
|
|
20
|
+
};
|
|
21
|
+
const canUseBlobDownload = () => typeof fetch === 'function' &&
|
|
22
|
+
typeof URL.createObjectURL === 'function' &&
|
|
23
|
+
typeof URL.revokeObjectURL === 'function';
|
|
24
|
+
const canUseFileShare = () => typeof File === 'function' &&
|
|
25
|
+
typeof navigator !== 'undefined' &&
|
|
26
|
+
typeof navigator.share === 'function' &&
|
|
27
|
+
typeof navigator.canShare === 'function';
|
|
28
|
+
const canShareFiles = (files) => canUseFileShare() && navigator.canShare({ files });
|
|
29
|
+
const getBlob = async (url) => {
|
|
30
|
+
const response = await fetch(url);
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw new Error('Network error');
|
|
33
|
+
}
|
|
34
|
+
return response.blob();
|
|
35
|
+
};
|
|
36
|
+
const isAbortError = (error) => typeof DOMException !== 'undefined' &&
|
|
37
|
+
error instanceof DOMException &&
|
|
38
|
+
error.name === 'AbortError';
|
|
39
|
+
const downloadFile = async ({ url, fileName = 'download', fileType, }) => {
|
|
40
|
+
if (!canUseBlobDownload()) {
|
|
41
|
+
downloadWithLink(url, fileName);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (canUseFileShare() && canShareFiles([new File([], fileName, { type: fileType })])) {
|
|
45
|
+
try {
|
|
46
|
+
const blob = await getBlob(url);
|
|
47
|
+
const file = new File([blob], fileName, { type: blob.type || fileType });
|
|
48
|
+
if (!canShareFiles([file])) {
|
|
49
|
+
downloadWithBlob(blob, fileName);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
await navigator.share({
|
|
53
|
+
files: [file],
|
|
54
|
+
title: `Скачать ${fileName}`,
|
|
55
|
+
});
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (isAbortError(error)) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
downloadWithLink(url, fileName);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const blob = await getBlob(url);
|
|
68
|
+
downloadWithBlob(blob, fileName);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
downloadWithLink(url, fileName);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export { downloadFile };
|
|
76
|
+
//# sourceMappingURL=modern-download.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modern-download.js","sources":["../../src/utils/modern-download.ts"],"sourcesContent":["const downloadWithBlob = (blob: Blob, fileName: string): void => {\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n\n link.href = url;\n link.download = fileName;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n setTimeout(() => URL.revokeObjectURL(url), 100);\n};\n\nconst downloadWithLink = (url: string, fileName: string): void => {\n const link = document.createElement('a');\n\n link.href = url;\n link.download = fileName;\n link.target = '_blank';\n link.rel = 'noopener noreferrer';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n};\n\nconst canUseBlobDownload = (): boolean =>\n typeof fetch === 'function' &&\n typeof URL.createObjectURL === 'function' &&\n typeof URL.revokeObjectURL === 'function';\n\nconst canUseFileShare = (): boolean =>\n typeof File === 'function' &&\n typeof navigator !== 'undefined' &&\n typeof navigator.share === 'function' &&\n typeof navigator.canShare === 'function';\n\nconst canShareFiles = (files: File[]): boolean =>\n canUseFileShare() && navigator.canShare({ files });\n\nconst getBlob = async (url: string): Promise<Blob> => {\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error('Network error');\n }\n\n return response.blob();\n};\n\nconst isAbortError = (error: unknown): boolean =>\n typeof DOMException !== 'undefined' &&\n error instanceof DOMException &&\n error.name === 'AbortError';\n\nexport interface DownloadOptions {\n url: string;\n fileName?: string;\n fileType?: string;\n}\n\nexport const downloadFile = async ({\n url,\n fileName = 'download',\n fileType,\n}: DownloadOptions): Promise<void> => {\n if (!canUseBlobDownload()) {\n downloadWithLink(url, fileName);\n\n return;\n }\n\n if (canUseFileShare() && canShareFiles([new File([], fileName, { type: fileType })])) {\n try {\n const blob = await getBlob(url);\n\n const file = new File([blob], fileName, { type: blob.type || fileType });\n\n if (!canShareFiles([file])) {\n downloadWithBlob(blob, fileName);\n\n return;\n }\n\n await navigator.share({\n files: [file],\n title: `Скачать ${fileName}`,\n });\n\n return;\n } catch (error) {\n if (isAbortError(error)) {\n return;\n }\n\n downloadWithLink(url, fileName);\n\n return;\n }\n }\n\n try {\n const blob = await getBlob(url);\n\n downloadWithBlob(blob, fileName);\n } catch {\n downloadWithLink(url, fileName);\n }\n};\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfalab/core-components-gallery",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.3.0-alfasans",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,20 +13,20 @@
|
|
|
13
13
|
"build": "rollup -c ../../tools/rollup/rollup.config.mjs --silent"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@alfalab/core-components-base-modal": "
|
|
17
|
-
"@alfalab/core-components-button": "
|
|
18
|
-
"@alfalab/core-components-icon-button": "
|
|
19
|
-
"@alfalab/core-components-icon-view": "
|
|
20
|
-
"@alfalab/core-components-mq": "
|
|
21
|
-
"@alfalab/core-components-
|
|
22
|
-
"@alfalab/core-components-
|
|
23
|
-
"@alfalab/core-components-
|
|
16
|
+
"@alfalab/core-components-base-modal": "7.1.8-alfasans",
|
|
17
|
+
"@alfalab/core-components-button": "13.2.2-alfasans",
|
|
18
|
+
"@alfalab/core-components-icon-button": "8.0.10-alfasans",
|
|
19
|
+
"@alfalab/core-components-icon-view": "5.0.4-alfasans",
|
|
20
|
+
"@alfalab/core-components-mq": "6.0.7-alfasans",
|
|
21
|
+
"@alfalab/core-components-shared": "2.2.3-alfasans",
|
|
22
|
+
"@alfalab/core-components-spinner": "6.0.7-alfasans",
|
|
23
|
+
"@alfalab/core-components-tooltip": "9.0.18-alfasans",
|
|
24
|
+
"@alfalab/core-components-typography": "6.0.10-alfasans",
|
|
24
25
|
"@alfalab/hooks": "^1.17.0",
|
|
25
26
|
"@alfalab/icons-glyph": "^2.260.0",
|
|
26
27
|
"classnames": "^2.5.1",
|
|
27
28
|
"element-closest": "^3.0.2",
|
|
28
29
|
"hls.js": "^1.5.13",
|
|
29
|
-
"lodash": "^4.17.21",
|
|
30
30
|
"swiper": "^12.1.3",
|
|
31
31
|
"tslib": "^2.4.0"
|
|
32
32
|
},
|
|
@@ -38,6 +38,6 @@
|
|
|
38
38
|
"access": "public",
|
|
39
39
|
"directory": "dist"
|
|
40
40
|
},
|
|
41
|
-
"themesVersion": "15.2.1",
|
|
42
|
-
"varsVersion": "11.2.1"
|
|
41
|
+
"themesVersion": "15.2.1-alfasans",
|
|
42
|
+
"varsVersion": "11.2.1-alfasans"
|
|
43
43
|
}
|
package/src/Component.tsx
CHANGED
|
@@ -88,6 +88,7 @@ export const Gallery: FC<GalleryProps> = ({
|
|
|
88
88
|
const [mutedVideo, setMutedVideo] = useState<boolean>(DEFAULT_MUTED_VIDEO);
|
|
89
89
|
const [playingVideo, setPlayingVideo] = useState<boolean>(DEFAULT_PLAYING_VIDEO);
|
|
90
90
|
const [hideNavigation, setHideNavigation] = useState<boolean>(DEFAULT_HIDE_NAVIGATION);
|
|
91
|
+
const [swipeY, setSwipeY] = useState<number>(0);
|
|
91
92
|
|
|
92
93
|
const isDesktop = useIsDesktop();
|
|
93
94
|
|
|
@@ -200,6 +201,12 @@ export const Gallery: FC<GalleryProps> = ({
|
|
|
200
201
|
}
|
|
201
202
|
}, [uncontrolled, currentSlideIndex, swiper]);
|
|
202
203
|
|
|
204
|
+
useEffect(() => {
|
|
205
|
+
if (!open) {
|
|
206
|
+
setSwipeY(0);
|
|
207
|
+
}
|
|
208
|
+
}, [open]);
|
|
209
|
+
|
|
203
210
|
useEffect(() => {
|
|
204
211
|
document.addEventListener('keydown', handleKeyDown);
|
|
205
212
|
|
|
@@ -209,14 +216,24 @@ export const Gallery: FC<GalleryProps> = ({
|
|
|
209
216
|
}, [handleKeyDown]);
|
|
210
217
|
|
|
211
218
|
useEffect(() => {
|
|
212
|
-
|
|
219
|
+
if (!open) {
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
let startX = 0;
|
|
224
|
+
let startY = 0;
|
|
225
|
+
let lockedDirection: 'horizontal' | 'vertical' | null = null;
|
|
226
|
+
const directionLockThreshold = 10;
|
|
227
|
+
|
|
213
228
|
const abortController = new AbortController();
|
|
214
229
|
const { signal } = abortController;
|
|
215
230
|
|
|
216
231
|
document.addEventListener(
|
|
217
232
|
'touchstart',
|
|
218
233
|
(e) => {
|
|
234
|
+
startX = e.touches[0].clientX;
|
|
219
235
|
startY = e.touches[0].clientY;
|
|
236
|
+
lockedDirection = null;
|
|
220
237
|
},
|
|
221
238
|
{ signal },
|
|
222
239
|
);
|
|
@@ -224,21 +241,57 @@ export const Gallery: FC<GalleryProps> = ({
|
|
|
224
241
|
document.addEventListener(
|
|
225
242
|
'touchmove',
|
|
226
243
|
(e) => {
|
|
227
|
-
const
|
|
228
|
-
const
|
|
244
|
+
const currentX = e.touches[0].clientX;
|
|
245
|
+
const currentY = e.touches[0].clientY;
|
|
246
|
+
const deltaX = currentX - startX;
|
|
247
|
+
const deltaY = currentY - startY;
|
|
248
|
+
|
|
249
|
+
if (!lockedDirection) {
|
|
250
|
+
const absX = Math.abs(deltaX);
|
|
251
|
+
const absY = Math.abs(deltaY);
|
|
252
|
+
|
|
253
|
+
if (absX > absY && absX > directionLockThreshold) {
|
|
254
|
+
lockedDirection = 'horizontal';
|
|
255
|
+
} else if (absY > absX && absY > directionLockThreshold) {
|
|
256
|
+
lockedDirection = 'vertical';
|
|
257
|
+
} else {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (lockedDirection === 'horizontal') {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
229
265
|
|
|
230
|
-
|
|
231
|
-
|
|
266
|
+
if (deltaY <= 0) {
|
|
267
|
+
setSwipeY(0);
|
|
268
|
+
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
setSwipeY(deltaY);
|
|
273
|
+
|
|
274
|
+
if (deltaY > SWIPE_THRESHOLD) {
|
|
275
|
+
setSwipeY(0);
|
|
232
276
|
onClose();
|
|
233
277
|
}
|
|
234
278
|
},
|
|
235
279
|
{ signal },
|
|
236
280
|
);
|
|
237
281
|
|
|
282
|
+
document.addEventListener(
|
|
283
|
+
'touchend',
|
|
284
|
+
() => {
|
|
285
|
+
lockedDirection = null;
|
|
286
|
+
setSwipeY(0);
|
|
287
|
+
},
|
|
288
|
+
{ signal },
|
|
289
|
+
);
|
|
290
|
+
|
|
238
291
|
return () => {
|
|
239
292
|
abortController.abort();
|
|
240
293
|
};
|
|
241
|
-
}, [onClose]);
|
|
294
|
+
}, [onClose, open]);
|
|
242
295
|
|
|
243
296
|
const singleSlide = images.length === 1;
|
|
244
297
|
|
|
@@ -282,6 +335,10 @@ export const Gallery: FC<GalleryProps> = ({
|
|
|
282
335
|
onUnmount={onUnmount}
|
|
283
336
|
>
|
|
284
337
|
<div
|
|
338
|
+
data-content-area={true}
|
|
339
|
+
style={{
|
|
340
|
+
transform: `translateY(${swipeY}px)`,
|
|
341
|
+
}}
|
|
285
342
|
className={cn(styles.container, {
|
|
286
343
|
[styles.mobile]: !isDesktop,
|
|
287
344
|
})}
|