@alfalab/core-components-gallery 5.7.4 → 5.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Component.js +47 -12
- package/components/buttons/index.css +35 -0
- package/{buttons-ec113bb4.d.ts → components/buttons/index.d.ts} +6 -1
- package/components/buttons/index.js +72 -0
- package/components/header/Component.js +33 -12
- package/components/header/index.css +5 -19
- package/components/header-info-block/Component.js +1 -1
- package/components/header-info-block/index.css +5 -5
- package/components/header-mobile/Component.d.ts +4 -0
- package/components/header-mobile/Component.js +39 -0
- package/components/header-mobile/index.css +50 -0
- package/components/header-mobile/index.d.ts +1 -0
- package/components/header-mobile/index.js +9 -0
- package/components/image-preview/Component.js +67 -24
- package/components/image-preview/index.css +35 -28
- package/components/image-preview/paths.d.ts +2 -0
- package/components/image-preview/paths.js +2 -0
- package/components/image-viewer/component.js +30 -10
- package/components/image-viewer/index.css +37 -25
- package/components/image-viewer/slide.js +3 -1
- package/components/image-viewer/video/index.css +48 -0
- package/components/image-viewer/video/index.d.ts +10 -0
- package/components/image-viewer/video/index.js +130 -0
- package/components/index.d.ts +2 -0
- package/components/index.js +4 -0
- package/components/info-bar/Component.d.ts +4 -0
- package/components/info-bar/Component.js +47 -0
- package/components/info-bar/index.css +37 -0
- package/components/info-bar/index.d.ts +1 -0
- package/components/info-bar/index.js +9 -0
- package/components/navigation-bar/Component.js +3 -2
- package/components/navigation-bar/index.css +8 -6
- package/context.d.ts +7 -0
- package/context.js +7 -0
- package/cssm/Component.js +46 -11
- package/cssm/components/{header/buttons.d.ts → buttons/index.d.ts} +6 -1
- package/cssm/components/buttons/index.js +71 -0
- package/cssm/components/buttons/index.module.css +34 -0
- package/cssm/components/header/Component.js +28 -10
- package/cssm/components/header/index.module.css +3 -17
- package/cssm/components/header-mobile/Component.d.ts +4 -0
- package/cssm/components/header-mobile/Component.js +38 -0
- package/cssm/components/header-mobile/index.d.ts +1 -0
- package/cssm/components/header-mobile/index.js +9 -0
- package/cssm/components/header-mobile/index.module.css +49 -0
- package/cssm/components/image-preview/Component.js +66 -27
- package/cssm/components/image-preview/index.module.css +25 -18
- package/cssm/components/image-preview/paths.d.ts +2 -0
- package/cssm/components/image-preview/paths.js +2 -0
- package/cssm/components/image-viewer/component.js +29 -9
- package/cssm/components/image-viewer/index.module.css +21 -9
- package/cssm/components/image-viewer/slide.js +12 -2
- package/cssm/components/image-viewer/video/index.d.ts +10 -0
- package/cssm/components/image-viewer/video/index.js +129 -0
- package/cssm/components/image-viewer/video/index.module.css +47 -0
- package/cssm/components/index.d.ts +2 -0
- package/cssm/components/index.js +4 -0
- package/cssm/components/info-bar/Component.d.ts +4 -0
- package/cssm/components/info-bar/Component.js +46 -0
- package/cssm/components/info-bar/index.d.ts +1 -0
- package/cssm/components/info-bar/index.js +9 -0
- package/cssm/components/info-bar/index.module.css +36 -0
- package/cssm/components/navigation-bar/Component.js +2 -1
- package/cssm/components/navigation-bar/index.module.css +3 -1
- package/cssm/context.d.ts +7 -0
- package/cssm/context.js +7 -0
- package/cssm/index.d.ts +1 -1
- package/cssm/index.js +1 -8
- package/cssm/index.module.css +14 -2
- package/cssm/types.d.ts +7 -0
- package/cssm/utils/constants.d.ts +14 -1
- package/cssm/utils/constants.js +19 -0
- package/cssm/utils/index.js +7 -0
- package/cssm/utils/utils.d.ts +2 -1
- package/cssm/utils/utils.js +5 -3
- package/esm/Component.js +46 -12
- package/esm/components/buttons/index.css +35 -0
- package/esm/{buttons-791da71e.d.ts → components/buttons/index.d.ts} +6 -1
- package/esm/components/buttons/index.js +55 -0
- package/esm/components/header/Component.js +30 -9
- package/esm/components/header/index.css +5 -19
- package/esm/components/header-info-block/Component.js +1 -1
- package/esm/components/header-info-block/index.css +5 -5
- package/esm/components/header-mobile/Component.d.ts +4 -0
- package/esm/components/header-mobile/Component.js +30 -0
- package/esm/components/header-mobile/index.css +50 -0
- package/esm/components/header-mobile/index.d.ts +1 -0
- package/esm/components/header-mobile/index.js +1 -0
- package/esm/components/image-preview/Component.js +69 -26
- package/esm/components/image-preview/index.css +35 -28
- package/esm/components/image-preview/paths.d.ts +2 -0
- package/esm/components/image-preview/paths.js +2 -0
- package/esm/components/image-viewer/component.js +31 -11
- package/esm/components/image-viewer/index.css +37 -25
- package/esm/components/image-viewer/slide.js +3 -1
- package/esm/components/image-viewer/video/index.css +48 -0
- package/esm/components/image-viewer/video/index.d.ts +10 -0
- package/esm/components/image-viewer/video/index.js +119 -0
- package/esm/components/index.d.ts +2 -0
- package/esm/components/index.js +2 -0
- package/esm/components/info-bar/Component.d.ts +4 -0
- package/esm/components/info-bar/Component.js +39 -0
- package/esm/components/info-bar/index.css +37 -0
- package/esm/components/info-bar/index.d.ts +1 -0
- package/esm/components/info-bar/index.js +1 -0
- package/esm/components/navigation-bar/Component.js +3 -2
- package/esm/components/navigation-bar/index.css +8 -6
- package/esm/context.d.ts +7 -0
- package/esm/context.js +7 -0
- package/esm/index.css +17 -5
- package/esm/index.d.ts +1 -1
- package/esm/index.js +1 -3
- package/esm/{slide-7d5a41d1.js → slide-c469a906.js} +15 -5
- package/esm/types.d.ts +7 -0
- package/esm/utils/constants.d.ts +14 -1
- package/esm/utils/constants.js +14 -1
- package/esm/utils/index.js +2 -2
- package/esm/utils/utils.d.ts +2 -1
- package/esm/utils/utils.js +5 -4
- package/index.css +17 -5
- package/index.d.ts +1 -1
- package/index.js +1 -8
- package/modern/Component.js +39 -7
- package/modern/components/buttons/index.css +35 -0
- package/modern/{buttons-1859cb8e.d.ts → components/buttons/index.d.ts} +6 -1
- package/modern/components/buttons/index.js +33 -0
- package/modern/components/header/Component.js +27 -9
- package/modern/components/header/index.css +5 -19
- package/modern/components/header-info-block/Component.js +1 -1
- package/modern/components/header-info-block/index.css +5 -5
- package/modern/components/header-mobile/Component.d.ts +4 -0
- package/modern/components/header-mobile/Component.js +28 -0
- package/modern/components/header-mobile/index.css +50 -0
- package/modern/components/header-mobile/index.d.ts +1 -0
- package/modern/components/header-mobile/index.js +1 -0
- package/modern/components/image-preview/Component.js +65 -23
- package/modern/components/image-preview/index.css +35 -28
- package/modern/components/image-preview/paths.d.ts +2 -0
- package/modern/components/image-preview/paths.js +2 -0
- package/modern/components/image-viewer/component.js +31 -11
- package/modern/components/image-viewer/index.css +37 -25
- package/modern/components/image-viewer/slide.js +3 -1
- package/modern/components/image-viewer/video/index.css +48 -0
- package/modern/components/image-viewer/video/index.d.ts +10 -0
- package/modern/components/image-viewer/video/index.js +117 -0
- package/modern/components/index.d.ts +2 -0
- package/modern/components/index.js +2 -0
- package/modern/components/info-bar/Component.d.ts +4 -0
- package/modern/components/info-bar/Component.js +38 -0
- package/modern/components/info-bar/index.css +37 -0
- package/modern/components/info-bar/index.d.ts +1 -0
- package/modern/components/info-bar/index.js +1 -0
- package/modern/components/navigation-bar/Component.js +3 -2
- package/modern/components/navigation-bar/index.css +8 -6
- package/modern/context.d.ts +7 -0
- package/modern/context.js +7 -0
- package/modern/index.css +17 -5
- package/modern/index.d.ts +1 -1
- package/modern/index.js +1 -3
- package/modern/{slide-c47386c3.js → slide-83826e9d.js} +15 -5
- package/modern/types.d.ts +7 -0
- package/modern/utils/constants.d.ts +14 -1
- package/modern/utils/constants.js +14 -1
- package/modern/utils/index.js +2 -2
- package/modern/utils/utils.d.ts +2 -1
- package/modern/utils/utils.js +5 -4
- package/moderncssm/Component.js +38 -6
- package/moderncssm/components/buttons/index.d.ts +16 -0
- package/moderncssm/components/buttons/index.js +31 -0
- package/moderncssm/components/buttons/index.module.css +20 -0
- package/moderncssm/components/header/Component.js +24 -9
- package/moderncssm/components/header/index.module.css +0 -19
- package/moderncssm/components/header-mobile/Component.d.ts +4 -0
- package/moderncssm/components/header-mobile/Component.js +26 -0
- package/moderncssm/components/header-mobile/index.d.ts +1 -0
- package/moderncssm/components/header-mobile/index.js +1 -0
- package/moderncssm/components/header-mobile/index.module.css +35 -0
- package/moderncssm/components/image-preview/Component.js +64 -26
- package/moderncssm/components/image-preview/index.module.css +30 -13
- package/moderncssm/components/image-preview/paths.d.ts +2 -0
- package/moderncssm/components/image-preview/paths.js +2 -0
- package/moderncssm/components/image-viewer/component.js +30 -10
- package/moderncssm/components/image-viewer/index.module.css +29 -6
- package/moderncssm/components/image-viewer/slide.js +14 -4
- package/moderncssm/components/image-viewer/video/index.d.ts +10 -0
- package/moderncssm/components/image-viewer/video/index.js +115 -0
- package/moderncssm/components/image-viewer/video/index.module.css +36 -0
- package/moderncssm/components/index.d.ts +2 -0
- package/moderncssm/components/index.js +2 -0
- package/moderncssm/components/info-bar/Component.d.ts +4 -0
- package/moderncssm/components/info-bar/Component.js +36 -0
- package/moderncssm/components/info-bar/index.d.ts +1 -0
- package/moderncssm/components/info-bar/index.js +1 -0
- package/moderncssm/components/info-bar/index.module.css +23 -0
- package/moderncssm/components/navigation-bar/Component.js +2 -1
- package/moderncssm/components/navigation-bar/index.module.css +4 -0
- package/moderncssm/context.d.ts +7 -0
- package/moderncssm/context.js +7 -0
- package/moderncssm/index.d.ts +1 -1
- package/moderncssm/index.js +1 -3
- package/moderncssm/index.module.css +18 -2
- package/moderncssm/types.d.ts +7 -0
- package/moderncssm/utils/constants.d.ts +14 -1
- package/moderncssm/utils/constants.js +14 -1
- package/moderncssm/utils/index.js +2 -2
- package/moderncssm/utils/utils.d.ts +2 -1
- package/moderncssm/utils/utils.js +5 -4
- package/package.json +2 -1
- package/{slide-12155967.js → slide-07755478.js} +13 -3
- package/src/Component.tsx +48 -6
- package/src/components/buttons/index.module.css +21 -0
- package/src/components/{header/buttons.tsx → buttons/index.tsx} +77 -0
- package/src/components/header/Component.tsx +33 -10
- package/src/components/header/index.module.css +0 -20
- package/src/components/header-mobile/Component.tsx +57 -0
- package/src/components/header-mobile/index.module.css +35 -0
- package/src/components/header-mobile/index.ts +1 -0
- package/src/components/image-preview/Component.tsx +131 -28
- package/src/components/image-preview/index.module.css +28 -9
- package/src/components/image-preview/paths.ts +3 -0
- package/src/components/image-viewer/component.tsx +32 -11
- package/src/components/image-viewer/index.module.css +26 -3
- package/src/components/image-viewer/slide.tsx +30 -4
- package/src/components/image-viewer/video/index.module.css +36 -0
- package/src/components/image-viewer/video/index.tsx +159 -0
- package/src/components/index.ts +2 -0
- package/src/components/info-bar/Component.tsx +68 -0
- package/src/components/info-bar/index.module.css +23 -0
- package/src/components/info-bar/index.ts +1 -0
- package/src/components/navigation-bar/Component.tsx +2 -1
- package/src/components/navigation-bar/index.module.css +4 -0
- package/src/context.ts +14 -0
- package/src/index.module.css +18 -2
- package/src/index.ts +1 -1
- package/src/types.ts +15 -5
- package/src/utils/constants.ts +17 -0
- package/src/utils/utils.ts +5 -3
- package/types.d.ts +7 -0
- package/utils/constants.d.ts +14 -1
- package/utils/constants.js +19 -0
- package/utils/index.js +7 -0
- package/utils/utils.d.ts +2 -1
- package/utils/utils.js +5 -3
- package/buttons-ec113bb4.js +0 -37
- package/components/header/buttons.d.ts +0 -0
- package/components/header/buttons.js +0 -20
- package/cssm/components/header/buttons.js +0 -37
- package/esm/buttons-791da71e.js +0 -27
- package/esm/components/header/buttons.d.ts +0 -0
- package/esm/components/header/buttons.js +0 -9
- package/modern/buttons-1859cb8e.js +0 -20
- package/modern/components/header/buttons.d.ts +0 -0
- package/modern/components/header/buttons.js +0 -8
- package/moderncssm/components/header/buttons.d.ts +0 -11
- package/moderncssm/components/header/buttons.js +0 -18
- /package/esm/{slide-7d5a41d1.d.ts → slide-c469a906.d.ts} +0 -0
- /package/modern/{slide-c47386c3.d.ts → slide-83826e9d.d.ts} +0 -0
- /package/{slide-12155967.d.ts → slide-07755478.d.ts} +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { FC, MutableRefObject } from 'react';
|
|
2
|
+
import { IconButtonProps } from "@alfalab/core-components-icon-button";
|
|
3
|
+
type Props = Omit<IconButtonProps, 'icon' | 'colors'> & {
|
|
4
|
+
buttonRef?: MutableRefObject<HTMLButtonElement | null>;
|
|
5
|
+
download?: string | boolean;
|
|
6
|
+
};
|
|
7
|
+
declare const Fullscreen: FC<Props>;
|
|
8
|
+
declare const BackArrow: FC<Props>;
|
|
9
|
+
declare const Play: FC<Props>;
|
|
10
|
+
declare const Pause: FC<Props>;
|
|
11
|
+
declare const ExitFullscreen: FC<Props>;
|
|
12
|
+
declare const MuteVideo: FC<Props>;
|
|
13
|
+
declare const UnmuteVideo: FC<Props>;
|
|
14
|
+
declare const Download: FC<Props>;
|
|
15
|
+
declare const Exit: FC<Props>;
|
|
16
|
+
export { Fullscreen, BackArrow, Play, Pause, ExitFullscreen, MuteVideo, UnmuteVideo, Download, Exit };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import cn from 'classnames';
|
|
3
|
+
import { IconButton } from '@alfalab/core-components-icon-button/moderncssm';
|
|
4
|
+
import { TooltipDesktop } from '@alfalab/core-components-tooltip/moderncssm/desktop';
|
|
5
|
+
import { ArrowLeftMIcon } from '@alfalab/icons-glyph/ArrowLeftMIcon';
|
|
6
|
+
import { ArrowsInwardMIcon } from '@alfalab/icons-glyph/ArrowsInwardMIcon';
|
|
7
|
+
import { ArrowsOutwardMIcon } from '@alfalab/icons-glyph/ArrowsOutwardMIcon';
|
|
8
|
+
import { CrossMIcon } from '@alfalab/icons-glyph/CrossMIcon';
|
|
9
|
+
import { PauseCompactMIcon } from '@alfalab/icons-glyph/PauseCompactMIcon';
|
|
10
|
+
import { PlayCompactMIcon } from '@alfalab/icons-glyph/PlayCompactMIcon';
|
|
11
|
+
import { PointerDownMIcon } from '@alfalab/icons-glyph/PointerDownMIcon';
|
|
12
|
+
import { SoundCrossMIcon } from '@alfalab/icons-glyph/SoundCrossMIcon';
|
|
13
|
+
import { SoundMIcon } from '@alfalab/icons-glyph/SoundMIcon';
|
|
14
|
+
import styles from './index.module.css';
|
|
15
|
+
|
|
16
|
+
const Fullscreen = ({ buttonRef, ...restProps }) => (React.createElement(TooltipDesktop, { trigger: 'hover', position: 'bottom', content: '\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u0432 \u043F\u043E\u043B\u043D\u043E\u044D\u043A\u0440\u0430\u043D\u043D\u043E\u043C \u0440\u0435\u0436\u0438\u043C\u0435', fallbackPlacements: ['bottom-end'] },
|
|
17
|
+
React.createElement(IconButton, { ...restProps, ref: buttonRef, icon: ArrowsOutwardMIcon, colors: 'inverted', "aria-label": '\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u0432 \u043F\u043E\u043B\u043D\u043E\u044D\u043A\u0440\u0430\u043D\u043D\u043E\u043C \u0440\u0435\u0436\u0438\u043C\u0435', className: styles.iconButton })));
|
|
18
|
+
const BackArrow = ({ buttonRef, ...restProps }) => (React.createElement(IconButton, { ...restProps, ref: buttonRef, icon: ArrowLeftMIcon, colors: 'inverted', "aria-label": '\u0412\u0435\u0440\u043D\u0443\u0442\u044C\u0441\u044F \u043D\u0430\u0437\u0430\u0434', className: styles.iconButton }));
|
|
19
|
+
const Play = ({ buttonRef, className, ...restProps }) => (React.createElement(IconButton, { ...restProps, ref: buttonRef, icon: PlayCompactMIcon, colors: 'inverted', "aria-label": '\u041F\u0440\u043E\u0438\u0433\u0440\u0430\u0442\u044C \u0432\u0438\u0434\u0435\u043E', className: cn(styles.iconButton, className) }));
|
|
20
|
+
const Pause = ({ buttonRef, className, ...restProps }) => (React.createElement(IconButton, { ...restProps, ref: buttonRef, icon: PauseCompactMIcon, colors: 'inverted', "aria-label": '\u041F\u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u043F\u0430\u0443\u0437\u0443 \u043D\u0430 \u0432\u0438\u0434\u0435\u043E', className: cn(styles.iconButton, className) }));
|
|
21
|
+
const ExitFullscreen = ({ buttonRef, ...restProps }) => (React.createElement(TooltipDesktop, { trigger: 'hover', position: 'bottom', content: '\u0412\u044B\u0439\u0442\u0438 \u0438\u0437 \u043F\u043E\u043B\u043D\u043E\u044D\u043A\u0440\u0430\u043D\u043D\u043E\u0433\u043E \u0440\u0435\u0436\u0438\u043C\u0430', fallbackPlacements: ['bottom-end'] },
|
|
22
|
+
React.createElement(IconButton, { ...restProps, ref: buttonRef, icon: ArrowsInwardMIcon, colors: 'inverted', "aria-label": '\u0412\u044B\u0439\u0442\u0438 \u0438\u0437 \u043F\u043E\u043B\u043D\u043E\u044D\u043A\u0440\u0430\u043D\u043D\u043E\u0433\u043E \u0440\u0435\u0436\u0438\u043C\u0430', className: styles.iconButton })));
|
|
23
|
+
const MuteVideo = ({ buttonRef, className, ...restProps }) => (React.createElement(TooltipDesktop, { trigger: 'hover', position: 'bottom', content: '\u0412\u044B\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0437\u0432\u0443\u043A', fallbackPlacements: ['bottom-end'], targetClassName: className },
|
|
24
|
+
React.createElement(IconButton, { ...restProps, ref: buttonRef, icon: SoundMIcon, colors: 'inverted', "aria-label": '\u0412\u044B\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0437\u0432\u0443\u043A', className: styles.iconButton })));
|
|
25
|
+
const UnmuteVideo = ({ buttonRef, className, ...restProps }) => (React.createElement(TooltipDesktop, { trigger: 'hover', position: 'bottom', content: '\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0437\u0432\u0443\u043A', fallbackPlacements: ['bottom-end'], targetClassName: className },
|
|
26
|
+
React.createElement(IconButton, { ...restProps, ref: buttonRef, icon: SoundCrossMIcon, colors: 'inverted', "aria-label": '\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0437\u0432\u0443\u043A', className: styles.iconButton })));
|
|
27
|
+
const Download = (props) => (React.createElement(TooltipDesktop, { trigger: 'hover', position: 'bottom', content: '\u0421\u043A\u0430\u0447\u0430\u0442\u044C', fallbackPlacements: ['bottom-end'] },
|
|
28
|
+
React.createElement(IconButton, { ...props, icon: PointerDownMIcon, colors: 'inverted', "aria-label": '\u0421\u043A\u0430\u0447\u0430\u0442\u044C', className: styles.iconButton })));
|
|
29
|
+
const Exit = (props) => (React.createElement(IconButton, { ...props, icon: CrossMIcon, colors: 'inverted', "aria-label": '\u0417\u0430\u043A\u0440\u044B\u0442\u044C', className: styles.iconButton }));
|
|
30
|
+
|
|
31
|
+
export { BackArrow, Download, Exit, ExitFullscreen, Fullscreen, MuteVideo, Pause, Play, UnmuteVideo };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/* */
|
|
2
|
+
|
|
3
|
+
.buttons {
|
|
4
|
+
display: flex;
|
|
5
|
+
padding-left: var(--gap-32)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.buttons path {
|
|
9
|
+
color: var(--color-static-neutral-translucent-1300-inverted);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/* TODO: применять static цвет через prop IconButton'а */
|
|
13
|
+
|
|
14
|
+
.iconButton:hover path {
|
|
15
|
+
color: var(--color-static-neutral-100-hover);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.iconButton:active path {
|
|
19
|
+
color: var(--color-static-neutral-100-press);
|
|
20
|
+
}
|
|
@@ -1,14 +1,31 @@
|
|
|
1
1
|
import React, { useContext, useRef, useEffect } from 'react';
|
|
2
2
|
import { GalleryContext } from '../../context.js';
|
|
3
|
-
import { isSmallImage } from '../../utils/utils.js';
|
|
4
|
-
import { TestIds } from '../../utils/constants.js';
|
|
3
|
+
import { isSmallImage, isVideo } from '../../utils/utils.js';
|
|
4
|
+
import { TestIds, GALLERY_EVENTS } from '../../utils/constants.js';
|
|
5
|
+
import { Download, Exit, ExitFullscreen, Fullscreen, UnmuteVideo, MuteVideo } from '../buttons/index.js';
|
|
5
6
|
import { HeaderInfoBlock } from '../header-info-block/Component.js';
|
|
6
|
-
import { Download, Exit, ExitFullscreen, Fullscreen } from './buttons.js';
|
|
7
7
|
import styles from './index.module.css';
|
|
8
8
|
|
|
9
9
|
const Header = () => {
|
|
10
|
-
const { currentSlideIndex, singleSlide, images, fullScreen, getCurrentImageMeta, getCurrentImage, setFullScreen, onClose, } = useContext(GalleryContext);
|
|
10
|
+
const { currentSlideIndex, singleSlide, images, fullScreen, getCurrentImageMeta, getCurrentImage, setFullScreen, onClose, mutedVideo, setMutedVideo, } = useContext(GalleryContext);
|
|
11
|
+
const currentImage = getCurrentImage();
|
|
12
|
+
const meta = getCurrentImageMeta();
|
|
11
13
|
const toggleFullScreenButton = useRef(null);
|
|
14
|
+
const onMuteButtonClick = () => {
|
|
15
|
+
if (mutedVideo) {
|
|
16
|
+
const customEvent = new CustomEvent(GALLERY_EVENTS.ON_UNMUTE, {
|
|
17
|
+
detail: { player: meta?.player?.current },
|
|
18
|
+
});
|
|
19
|
+
dispatchEvent(customEvent);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
const customEvent = new CustomEvent(GALLERY_EVENTS.ON_MUTE, {
|
|
23
|
+
detail: { player: meta?.player?.current },
|
|
24
|
+
});
|
|
25
|
+
dispatchEvent(customEvent);
|
|
26
|
+
}
|
|
27
|
+
setMutedVideo(!mutedVideo);
|
|
28
|
+
};
|
|
12
29
|
const closeFullScreen = () => {
|
|
13
30
|
setFullScreen(false);
|
|
14
31
|
};
|
|
@@ -20,19 +37,17 @@ const Header = () => {
|
|
|
20
37
|
toggleFullScreenButton.current.focus();
|
|
21
38
|
}
|
|
22
39
|
}, [fullScreen]);
|
|
23
|
-
const currentImage = getCurrentImage();
|
|
24
40
|
const canDownload = currentImage?.canDownload ?? true;
|
|
25
41
|
const filename = currentImage?.name || '';
|
|
26
|
-
const description = singleSlide || !images.length
|
|
27
|
-
? ''
|
|
28
|
-
: `Изображение ${currentSlideIndex + 1} из ${images.length}`;
|
|
29
|
-
const meta = getCurrentImageMeta();
|
|
42
|
+
const description = singleSlide || !images.length ? '' : `${currentSlideIndex + 1} из ${images.length}`;
|
|
30
43
|
const showFullScreenButton = !isSmallImage(meta) && !meta?.broken;
|
|
31
44
|
const showDownloadButton = !meta?.broken && canDownload;
|
|
32
45
|
const renderToggleFullScreenButton = () => fullScreen ? (React.createElement(ExitFullscreen, { onClick: closeFullScreen, buttonRef: toggleFullScreenButton, dataTestId: TestIds.EXIT_FULLSCREEN_BUTTON })) : (React.createElement(Fullscreen, { onClick: openFullScreen, buttonRef: toggleFullScreenButton, dataTestId: TestIds.FULLSCREEN_BUTTON }));
|
|
46
|
+
const renderToggleMuteVideo = () => mutedVideo ? (React.createElement(UnmuteVideo, { onClick: onMuteButtonClick, dataTestId: TestIds.UNMUTE_BUTTON })) : (React.createElement(MuteVideo, { onClick: onMuteButtonClick, dataTestId: TestIds.MUTE_BUTTON }));
|
|
33
47
|
return (React.createElement("div", { className: styles.header },
|
|
34
48
|
React.createElement(HeaderInfoBlock, { filename: filename, description: description }),
|
|
35
49
|
React.createElement("div", { className: styles.buttons },
|
|
50
|
+
isVideo(currentImage?.src) && renderToggleMuteVideo(),
|
|
36
51
|
showFullScreenButton && renderToggleFullScreenButton(),
|
|
37
52
|
showDownloadButton && (React.createElement(Download, { href: currentImage?.src, download: currentImage?.name, dataTestId: TestIds.DOWNLOAD_BUTTON })),
|
|
38
53
|
React.createElement(Exit, { onClick: onClose, dataTestId: TestIds.CLOSE_BUTTON }))));
|
|
@@ -8,22 +8,3 @@
|
|
|
8
8
|
padding: var(--gap-16) var(--gap-24);
|
|
9
9
|
box-sizing: border-box;
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
.buttons {
|
|
13
|
-
display: flex;
|
|
14
|
-
padding-left: var(--gap-32)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.buttons path {
|
|
18
|
-
color: var(--color-static-neutral-translucent-1300-inverted);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/* TODO: применять static цвет через prop IconButton'а */
|
|
22
|
-
|
|
23
|
-
.iconButton:hover path {
|
|
24
|
-
color: var(--color-static-neutral-100-hover);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
.iconButton:active path {
|
|
28
|
-
color: var(--color-static-neutral-100-press);
|
|
29
|
-
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
import cn from 'classnames';
|
|
3
|
+
import { Typography } from '@alfalab/core-components-typography/moderncssm';
|
|
4
|
+
import { GalleryContext } from '../../context.js';
|
|
5
|
+
import { isVideo } from '../../utils/utils.js';
|
|
6
|
+
import { TestIds } from '../../utils/constants.js';
|
|
7
|
+
import { BackArrow, Download } from '../buttons/index.js';
|
|
8
|
+
import styles from './index.module.css';
|
|
9
|
+
|
|
10
|
+
const HeaderMobile = () => {
|
|
11
|
+
const { onClose, images, currentSlideIndex, getCurrentImage, getCurrentImageMeta, hideNavigation, } = useContext(GalleryContext);
|
|
12
|
+
const currentImage = getCurrentImage();
|
|
13
|
+
const meta = getCurrentImageMeta();
|
|
14
|
+
const description = images.length > 1 && `${currentSlideIndex + 1} из ${images.length}`;
|
|
15
|
+
const canDownload = currentImage?.canDownload ?? true;
|
|
16
|
+
const showDownloadButton = !meta?.broken && canDownload;
|
|
17
|
+
return (React.createElement("div", { className: cn(styles.headerMobile, {
|
|
18
|
+
[styles.video]: isVideo(currentImage?.src),
|
|
19
|
+
[styles.hide]: hideNavigation,
|
|
20
|
+
}) },
|
|
21
|
+
React.createElement(BackArrow, { onClick: onClose }),
|
|
22
|
+
React.createElement(Typography.Text, { className: styles.description, tag: 'div', view: 'component-primary', color: 'static-primary-light' }, description),
|
|
23
|
+
React.createElement("div", { className: styles.rightButtons }, showDownloadButton && (React.createElement(Download, { href: currentImage?.src, download: currentImage?.name, dataTestId: TestIds.DOWNLOAD_BUTTON })))));
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export { HeaderMobile };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { HeaderMobile } from "./Component";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { HeaderMobile } from './Component.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* */
|
|
2
|
+
|
|
3
|
+
.headerMobile {
|
|
4
|
+
position: relative;
|
|
5
|
+
height: 72px;
|
|
6
|
+
z-index: 3;
|
|
7
|
+
padding: var(--gap-12) var(--gap-8);
|
|
8
|
+
display: flex;
|
|
9
|
+
justify-content: space-between;
|
|
10
|
+
align-items: center
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.headerMobile.video {
|
|
14
|
+
position: absolute;
|
|
15
|
+
width: 100%;
|
|
16
|
+
padding: 0;
|
|
17
|
+
background-color: var(--color-static-neutral-0-inverted);
|
|
18
|
+
transition: transform 0.3s ease-in-out;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.hide {
|
|
22
|
+
transform: translateY(-96px);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.leftButton,
|
|
26
|
+
.rightButtons {
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.description {
|
|
32
|
+
position: absolute;
|
|
33
|
+
left: 50%;
|
|
34
|
+
transform: translateX(-50%);
|
|
35
|
+
}
|
|
@@ -1,27 +1,38 @@
|
|
|
1
|
-
import React, { useContext, useRef } from 'react';
|
|
1
|
+
import React, { useContext, useRef, useEffect } from 'react';
|
|
2
2
|
import cn from 'classnames';
|
|
3
|
-
import '@alfalab/core-components-base-modal/moderncssm';
|
|
4
|
-
import { GalleryContext } from '../../context.js';
|
|
5
|
-
import { getImageAlt } from '../../utils/utils.js';
|
|
6
|
-
import '../navigation-bar/index.module.css';
|
|
7
|
-
import '@alfalab/core-components-typography/moderncssm';
|
|
8
|
-
import '../header-info-block/index.module.css';
|
|
9
|
-
import '@alfalab/core-components-icon-button/moderncssm';
|
|
10
|
-
import '@alfalab/core-components-tooltip/moderncssm/desktop';
|
|
11
|
-
import '@alfalab/icons-glyph/ArrowsInwardMIcon';
|
|
12
|
-
import '@alfalab/icons-glyph/ArrowsOutwardMIcon';
|
|
13
|
-
import '@alfalab/icons-glyph/CrossMIcon';
|
|
14
|
-
import '@alfalab/icons-glyph/PointerDownMIcon';
|
|
15
|
-
import '../header/index.module.css';
|
|
16
|
-
import '../image-viewer/component.js';
|
|
17
|
-
import '../../index.module.css';
|
|
18
3
|
import { useFocus } from '@alfalab/hooks';
|
|
4
|
+
import { GalleryContext } from '../../context.js';
|
|
5
|
+
import { isVideo, getImageAlt } from '../../utils/utils.js';
|
|
6
|
+
import { PREVIEW_VIDEO_MULTIPLIER, PREVIEW_WIDTH_MOBILE, PREVIEW_WIDTH_DESKTOP, PREVIEW_HEIGHT_MOBILE, PREVIEW_HEIGHT_DESKTOP } from '../../utils/constants.js';
|
|
19
7
|
import { NoImagePaths } from './paths.js';
|
|
20
8
|
import styles from './index.module.css';
|
|
21
9
|
|
|
22
10
|
const ImagePreview = ({ image, active = false, index, onSelect, className }) => {
|
|
23
|
-
const { imagesMeta } = useContext(GalleryContext);
|
|
11
|
+
const { imagesMeta, view } = useContext(GalleryContext);
|
|
12
|
+
const isMobile = view === 'mobile';
|
|
13
|
+
const previewWidth = isMobile ? PREVIEW_WIDTH_MOBILE : PREVIEW_WIDTH_DESKTOP;
|
|
14
|
+
const previewHeight = isMobile ? PREVIEW_HEIGHT_MOBILE : PREVIEW_HEIGHT_DESKTOP;
|
|
24
15
|
const ref = useRef(null);
|
|
16
|
+
const canvasRef = useRef(null);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const canvas = canvasRef.current;
|
|
19
|
+
const video = imagesMeta[index]?.player?.current;
|
|
20
|
+
const context = canvas?.getContext('2d');
|
|
21
|
+
const drawPreview = () => {
|
|
22
|
+
if (video) {
|
|
23
|
+
context?.drawImage(video, 0, 0, video.videoWidth / PREVIEW_VIDEO_MULTIPLIER, video.videoHeight / PREVIEW_VIDEO_MULTIPLIER);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
drawPreview();
|
|
27
|
+
if (isVideo(image.src)) {
|
|
28
|
+
video?.addEventListener('canplay', drawPreview);
|
|
29
|
+
}
|
|
30
|
+
return () => {
|
|
31
|
+
if (isVideo(image.src)) {
|
|
32
|
+
video?.removeEventListener('canplay', drawPreview);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}, [image.src, imagesMeta, index]);
|
|
25
36
|
const handleClick = () => {
|
|
26
37
|
onSelect(index);
|
|
27
38
|
};
|
|
@@ -33,15 +44,42 @@ const ImagePreview = ({ image, active = false, index, onSelect, className }) =>
|
|
|
33
44
|
const [focused] = useFocus(ref, 'keyboard');
|
|
34
45
|
const meta = imagesMeta[index];
|
|
35
46
|
const isBroken = Boolean(meta?.broken);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
React.createElement("
|
|
39
|
-
React.createElement("
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
47
|
+
const renderPreview = () => {
|
|
48
|
+
if (isBroken) {
|
|
49
|
+
return (React.createElement("div", { className: cn(styles.preview, { [styles.mobile]: isMobile, [styles.active]: active }, styles.brokenImageWrapper) },
|
|
50
|
+
React.createElement("div", { className: cn(styles.brokenIcon) },
|
|
51
|
+
React.createElement("svg", { xmlns: 'http://www.w3.org/2000/svg', width: previewWidth, height: previewHeight, viewBox: `${isMobile ? -6 : 0} ${isMobile ? -12 : 0} ${previewWidth} ${previewHeight}`, fill: 'none' },
|
|
52
|
+
React.createElement("rect", { fill: 'none' }),
|
|
53
|
+
React.createElement("path", { fillRule: 'evenodd', clipRule: 'evenodd', d: isMobile ? NoImagePaths.mobileImage : NoImagePaths.baseImage, fill: '#89898A' }),
|
|
54
|
+
React.createElement("path", { d: isMobile
|
|
55
|
+
? NoImagePaths.mobileTriangle
|
|
56
|
+
: NoImagePaths.triangleImage, fill: '#89898A' })))));
|
|
57
|
+
}
|
|
58
|
+
if (image.previewSrc) {
|
|
59
|
+
return (React.createElement("div", { className: cn(styles.preview, styles.image, {
|
|
60
|
+
[styles.loading]: !meta,
|
|
61
|
+
[styles.mobile]: isMobile,
|
|
62
|
+
}) },
|
|
63
|
+
React.createElement("img", { src: image.previewSrc, alt: getImageAlt(image, index) })));
|
|
64
|
+
}
|
|
65
|
+
if (isVideo(image.src)) {
|
|
66
|
+
return (React.createElement("div", { className: cn(styles.preview, styles.image, {
|
|
67
|
+
[styles.loading]: !meta,
|
|
68
|
+
[styles.mobile]: isMobile,
|
|
69
|
+
}) },
|
|
70
|
+
React.createElement("canvas", { className: cn(styles.canvasPreview, { [styles.mobile]: isMobile }), "data-testid": 'canvas', width: previewWidth, height: previewHeight, ref: canvasRef })));
|
|
71
|
+
}
|
|
72
|
+
return (React.createElement("div", { className: cn(styles.preview, styles.image, {
|
|
73
|
+
[styles.loading]: !meta,
|
|
74
|
+
[styles.mobile]: isMobile,
|
|
75
|
+
}) },
|
|
76
|
+
React.createElement("img", { src: image.src, alt: getImageAlt(image, index) })));
|
|
77
|
+
};
|
|
78
|
+
return (React.createElement("div", { className: cn(styles.component, {
|
|
79
|
+
[styles.active]: active,
|
|
80
|
+
[styles.focused]: focused,
|
|
81
|
+
[styles.mobile]: isMobile,
|
|
82
|
+
}, className), onClick: handleClick, role: 'button', onKeyDown: handleKeyDown, tabIndex: 0, ref: ref, "aria-label": `Перейти к ${index + 1} элементу` }, renderPreview()));
|
|
45
83
|
};
|
|
46
84
|
|
|
47
85
|
export { ImagePreview };
|
|
@@ -3,38 +3,46 @@
|
|
|
3
3
|
.component {
|
|
4
4
|
display: flex;
|
|
5
5
|
padding: var(--gap-4);
|
|
6
|
-
|
|
7
|
-
border-radius: var(--border-radius-12);
|
|
6
|
+
z-index: 3;
|
|
8
7
|
overflow: hidden;
|
|
9
8
|
transition: border 0.15s ease-in-out;
|
|
10
|
-
outline: none
|
|
9
|
+
outline: none
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
.
|
|
14
|
-
|
|
15
|
-
}
|
|
12
|
+
.component .image {
|
|
13
|
+
opacity: 0.3;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.component.mobile {
|
|
17
|
+
padding: 0;
|
|
18
|
+
}
|
|
16
19
|
|
|
17
20
|
.active > .image {
|
|
18
|
-
opacity:
|
|
21
|
+
opacity: 1;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
.preview {
|
|
22
25
|
width: 56px;
|
|
23
26
|
height: 56px;
|
|
24
27
|
flex-shrink: 0;
|
|
25
|
-
border-radius: var(--border-radius-
|
|
28
|
+
border-radius: var(--border-radius-12);
|
|
26
29
|
cursor: pointer;
|
|
27
30
|
-webkit-user-select: none;
|
|
28
|
-
user-select: none
|
|
31
|
+
user-select: none
|
|
29
32
|
}
|
|
30
33
|
|
|
34
|
+
.preview.mobile {
|
|
35
|
+
width: 36px;
|
|
36
|
+
height: 46px;
|
|
37
|
+
border-radius: var(--border-radius-8);
|
|
38
|
+
}
|
|
39
|
+
|
|
31
40
|
.image {
|
|
32
41
|
transition: opacity 0.15s ease-in-out
|
|
33
42
|
}
|
|
34
43
|
|
|
35
44
|
.image > img {
|
|
36
45
|
display: block;
|
|
37
|
-
background-color: var(--color-light-base-bg-primary);
|
|
38
46
|
width: 100%;
|
|
39
47
|
height: 100%;
|
|
40
48
|
border-radius: inherit;
|
|
@@ -59,11 +67,12 @@
|
|
|
59
67
|
display: flex;
|
|
60
68
|
justify-content: center;
|
|
61
69
|
align-items: center;
|
|
62
|
-
background-color: var(--color-static-neutral-300-inverted)
|
|
70
|
+
background-color: var(--color-static-neutral-300-inverted);
|
|
71
|
+
opacity: 0.3
|
|
63
72
|
}
|
|
64
73
|
|
|
65
|
-
.brokenImageWrapper
|
|
66
|
-
opacity:
|
|
74
|
+
.brokenImageWrapper.active {
|
|
75
|
+
opacity: 1;
|
|
67
76
|
}
|
|
68
77
|
|
|
69
78
|
.brokenIcon {
|
|
@@ -75,3 +84,11 @@
|
|
|
75
84
|
outline: 2px solid var(--focus-color);
|
|
76
85
|
outline-offset: 2px;
|
|
77
86
|
}
|
|
87
|
+
|
|
88
|
+
.canvasPreview {
|
|
89
|
+
border-radius: var(--border-radius-12)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.canvasPreview.mobile {
|
|
93
|
+
border-radius: var(--border-radius-8);
|
|
94
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const NoImagePaths = {
|
|
2
2
|
baseImage: 'M 30.5 6.5 L 4 6.5 C 2.894531 6.5 2 7.394531 2 8.5 L 2 31.5 C 2 32.605469 2.894531 33.5 4 33.5 L 36 33.5 C 37.105469 33.5 38 32.605469 38 31.5 L 38 14 L 32.367188 14 C 31.335938 14 30.5 13.164062 30.5 12.132812 Z M 11.917969 15.667969 C 12.285156 15.296875 12.882812 15.296875 13.25 15.667969 L 14.25 16.667969 L 15.25 15.667969 C 15.617188 15.296875 16.214844 15.296875 16.582031 15.667969 C 16.953125 16.035156 16.953125 16.632812 16.582031 17 L 15.582031 18 L 16.582031 19 C 16.953125 19.367188 16.953125 19.964844 16.582031 20.332031 C 16.214844 20.703125 15.617188 20.703125 15.25 20.332031 L 14.25 19.332031 L 13.25 20.332031 C 12.882812 20.703125 12.285156 20.703125 11.917969 20.332031 C 11.546875 19.964844 11.546875 19.367188 11.917969 19 L 12.917969 18 L 11.917969 17 C 11.546875 16.632812 11.546875 16.035156 11.917969 15.667969 Z M 24.75 15.667969 C 24.382812 15.296875 23.785156 15.296875 23.414062 15.667969 C 23.046875 16.035156 23.046875 16.632812 23.414062 17 L 24.414062 18 L 23.414062 19 C 23.046875 19.367188 23.046875 19.964844 23.414062 20.332031 C 23.785156 20.703125 24.378906 20.703125 24.75 20.332031 L 25.75 19.332031 L 26.75 20.332031 C 27.117188 20.703125 27.714844 20.703125 28.082031 20.332031 C 28.449219 19.964844 28.449219 19.367188 28.082031 19 L 27.082031 18 L 28.082031 17 C 28.449219 16.632812 28.449219 16.035156 28.082031 15.667969 C 27.714844 15.296875 27.117188 15.296875 26.75 15.667969 L 25.75 16.667969 Z M 14.40625 27.914062 L 14.402344 27.914062 C 13.898438 28.136719 13.308594 27.910156 13.085938 27.40625 C 12.863281 26.902344 13.089844 26.308594 13.59375 26.085938 L 14 27 C 13.59375 26.085938 13.59375 26.085938 13.59375 26.085938 L 13.597656 26.085938 L 13.601562 26.082031 L 13.609375 26.078125 L 13.621094 26.074219 L 13.636719 26.066406 C 13.660156 26.058594 13.695312 26.042969 13.734375 26.027344 C 13.816406 25.996094 13.933594 25.949219 14.082031 25.898438 C 14.378906 25.796875 14.808594 25.660156 15.359375 25.527344 C 16.457031 25.261719 18.035156 25 20 25 C 21.964844 25 23.542969 25.261719 24.640625 25.527344 C 25.191406 25.660156 25.621094 25.796875 25.917969 25.898438 C 25.96875 25.917969 26.015625 25.933594 26.058594 25.949219 C 26.144531 25.980469 26.210938 26.007812 26.265625 26.027344 C 26.285156 26.035156 26.304688 26.042969 26.320312 26.050781 C 26.335938 26.054688 26.351562 26.0625 26.363281 26.066406 L 26.382812 26.078125 L 26.390625 26.078125 L 26.398438 26.082031 L 26.402344 26.085938 L 26.40625 26.085938 C 26.40625 26.085938 26.40625 26.085938 26.402344 26.089844 L 26.398438 26.105469 L 26.40625 26.085938 C 26.910156 26.308594 27.136719 26.902344 26.914062 27.40625 C 26.691406 27.910156 26.101562 28.136719 25.597656 27.914062 L 20.449219 27.914062 L 25.59375 27.914062 L 25.585938 27.910156 C 25.574219 27.90625 25.554688 27.898438 25.527344 27.886719 C 25.472656 27.863281 25.382812 27.832031 25.261719 27.789062 C 25.019531 27.703125 24.652344 27.589844 24.171875 27.472656 C 23.207031 27.238281 21.785156 27 20 27 C 18.214844 27 16.792969 27.238281 15.828125 27.472656 C 15.347656 27.589844 14.980469 27.703125 14.738281 27.789062 C 14.617188 27.832031 14.527344 27.863281 14.472656 27.886719 C 14.445312 27.898438 14.425781 27.90625 14.414062 27.910156 L 14.40625 27.914062 L 20.449219 27.914062 Z M 14.40625 27.914062',
|
|
3
3
|
triangleImage: 'M 38 12 L 32.5 12 L 32.5 6.5 Z M 38 12',
|
|
4
|
+
mobileImage: 'M19 0H1.33333C0.596954 0 0 0.596944 0 1.33333V16.6667C0 17.4031 0.596954 18 1.33333 18H22.6667C23.403 18 24 17.4031 24 16.6667V4.99995H20.2444C19.5571 4.99995 19 4.44279 19 3.7555V0ZM6.61123 6.11112C6.85668 5.86566 7.25465 5.86566 7.5001 6.11112L8.1667 6.77773L8.83331 6.1111C9.07878 5.86564 9.47675 5.86564 9.7222 6.1111C9.96766 6.35657 9.96766 6.75454 9.7222 7L9.05558 7.66661L9.72231 8.33333C9.96777 8.57878 9.96777 8.97675 9.72231 9.22221C9.47686 9.46767 9.07889 9.46767 8.83344 9.22221L8.16671 8.55548L7.49999 9.22221C7.25454 9.46765 6.85657 9.46765 6.6111 9.22221C6.36565 8.97675 6.36565 8.57878 6.6111 8.33331L7.27782 7.66659L6.61123 7C6.36576 6.75454 6.36576 6.35657 6.61123 6.11112ZM15.1661 6.11112C14.9207 5.86566 14.5227 5.86566 14.2772 6.11112C14.0318 6.35659 14.0318 6.75456 14.2772 7L14.9438 7.66661L14.2771 8.33333C14.0317 8.57878 14.0317 8.97675 14.2771 9.22221C14.5226 9.46767 14.9206 9.46767 15.166 9.22221L15.8327 8.55548L16.4995 9.22221C16.7449 9.46767 17.1429 9.46767 17.3883 9.22221C17.6338 8.97677 17.6338 8.5788 17.3883 8.33333L16.7216 7.66661L17.3882 7C17.6337 6.75454 17.6337 6.35657 17.3882 6.11112C17.1428 5.86566 16.7448 5.86566 16.4993 6.11112L15.8327 6.77773L15.1661 6.11112ZM8.26956 14.2764L8.26919 14.2766C7.93322 14.4248 7.54007 14.2733 7.39079 13.9374C7.24125 13.601 7.39278 13.207 7.72924 13.0575L8 13.6667C7.72924 13.0575 7.72962 13.0573 7.72962 13.0573L7.73005 13.0571L7.73099 13.0567L7.7333 13.0557L7.73957 13.0529L7.74749 13.0495L7.75875 13.0448C7.77446 13.0381 7.796 13.0293 7.82326 13.0184C7.87777 12.9968 7.95515 12.9674 8.05442 12.9328C8.25294 12.8638 8.53925 12.7742 8.90544 12.6854C9.63773 12.5079 10.6907 12.3333 12 12.3333C13.3093 12.3333 14.3623 12.5079 15.0946 12.6854C15.4608 12.7742 15.7471 12.8638 15.9456 12.9328C15.9796 12.9447 16.011 12.9559 16.0398 12.9664C16.0952 12.9866 16.1409 13.0042 16.1767 13.0184C16.1901 13.0238 16.2022 13.0286 16.2128 13.033C16.2238 13.0375 16.2333 13.0414 16.2413 13.0448L16.2559 13.051L16.2604 13.0529L16.2667 13.0557L16.269 13.0567L16.27 13.0571L16.2704 13.0573C16.2704 13.0573 16.2704 13.0573 16.2692 13.0602L16.2646 13.0707L16.2708 13.0575C16.6072 13.207 16.7587 13.601 16.6092 13.9374C16.4599 14.2733 16.0671 14.4249 15.731 14.2767L15.7304 14.2764L12.2987 14.2764L15.73 14.2762L15.7238 14.2736C15.7163 14.2704 15.7032 14.265 15.6846 14.2576C15.6473 14.2428 15.588 14.2201 15.5075 14.1922C15.3467 14.1362 15.1017 14.0591 14.7804 13.9812C14.1377 13.8254 13.1907 13.6667 12 13.6667C10.8093 13.6667 9.86227 13.8254 9.21956 13.9812C8.89825 14.0591 8.65331 14.1362 8.49245 14.1922C8.41204 14.2201 8.3527 14.2428 8.31541 14.2576C8.29677 14.265 8.28365 14.2704 8.27616 14.2736L8.27041 14.276L12.2987 14.2764L8.26956 14.2764Z',
|
|
5
|
+
mobileTriangle: 'M23.9999 3.66661H20.3333V0L23.9999 3.66661Z',
|
|
4
6
|
};
|
|
5
7
|
|
|
6
8
|
export { NoImagePaths };
|
|
@@ -7,7 +7,7 @@ import { useFocus } from '@alfalab/hooks';
|
|
|
7
7
|
import { ChevronBackHeavyMIcon } from '@alfalab/icons-glyph/ChevronBackHeavyMIcon';
|
|
8
8
|
import { ChevronForwardHeavyMIcon } from '@alfalab/icons-glyph/ChevronForwardHeavyMIcon';
|
|
9
9
|
import { GalleryContext } from '../../context.js';
|
|
10
|
-
import { getImageAlt, getImageKey } from '../../utils/utils.js';
|
|
10
|
+
import { isVideo, getImageAlt, getImageKey } from '../../utils/utils.js';
|
|
11
11
|
import { TestIds } from '../../utils/constants.js';
|
|
12
12
|
import { Slide } from './slide.js';
|
|
13
13
|
import 'swiper/swiper.min.css';
|
|
@@ -15,12 +15,14 @@ import styles from './index.module.css';
|
|
|
15
15
|
|
|
16
16
|
SwiperCore.use([EffectFade, A11y, Controller]);
|
|
17
17
|
const ImageViewer = () => {
|
|
18
|
-
const { singleSlide, images, imagesMeta, fullScreen, currentSlideIndex, initialSlide, onClose,
|
|
18
|
+
const { singleSlide, images, imagesMeta, fullScreen, currentSlideIndex, initialSlide, onClose, setImageMeta, setCurrentSlideIndex, getSwiper, setSwiper, slidePrev, slideNext, getCurrentImage, view, } = useContext(GalleryContext);
|
|
19
|
+
const isMobile = view === 'mobile';
|
|
19
20
|
const leftArrowRef = useRef(null);
|
|
20
21
|
const rightArrowRef = useRef(null);
|
|
21
22
|
const [leftArrowFocused] = useFocus(leftArrowRef, 'keyboard');
|
|
22
23
|
const [rightArrowFocused] = useFocus(rightArrowRef, 'keyboard');
|
|
23
24
|
const swiper = getSwiper();
|
|
25
|
+
const currentImage = getCurrentImage();
|
|
24
26
|
const handleSlideChange = useCallback(() => {
|
|
25
27
|
setCurrentSlideIndex?.(swiper?.activeIndex ?? initialSlide);
|
|
26
28
|
}, [setCurrentSlideIndex, swiper, initialSlide]);
|
|
@@ -54,10 +56,10 @@ const ImageViewer = () => {
|
|
|
54
56
|
rightArrowRef.current?.contains(eventTarget);
|
|
55
57
|
const isPlaceholder = Boolean(eventTarget.closest(`.${styles.placeholder}`));
|
|
56
58
|
const isImg = eventTarget.tagName === 'IMG';
|
|
57
|
-
if (!isImg && !isPlaceholder && !isArrow) {
|
|
59
|
+
if (!isImg && !isPlaceholder && !isArrow && !isMobile) {
|
|
58
60
|
onClose();
|
|
59
61
|
}
|
|
60
|
-
}, [onClose]);
|
|
62
|
+
}, [isMobile, onClose]);
|
|
61
63
|
useEffect(() => {
|
|
62
64
|
elementClosest(window);
|
|
63
65
|
}, []);
|
|
@@ -67,29 +69,47 @@ const ImageViewer = () => {
|
|
|
67
69
|
fadeEffect: {
|
|
68
70
|
crossFade: true,
|
|
69
71
|
},
|
|
70
|
-
className: cn(styles.swiper, {
|
|
72
|
+
className: cn(styles.swiper, {
|
|
73
|
+
[styles.hidden]: fullScreen && !isVideo(currentImage?.src),
|
|
74
|
+
[styles.fullScreenVideo]: fullScreen && !singleSlide && isVideo(currentImage?.src),
|
|
75
|
+
[styles.mobile]: isMobile,
|
|
76
|
+
[styles.mobileVideo]: isMobile && isVideo(currentImage?.src),
|
|
77
|
+
}),
|
|
71
78
|
controller: { control: swiper },
|
|
72
79
|
a11y: {
|
|
73
80
|
slideRole: 'img',
|
|
74
81
|
},
|
|
75
82
|
initialSlide,
|
|
76
83
|
simulateTouch: false,
|
|
84
|
+
zoom: { maxRatio: 4 },
|
|
77
85
|
onSwiper: setSwiper,
|
|
78
86
|
onSlideChange: handleSlideChange,
|
|
79
|
-
}), [
|
|
80
|
-
|
|
87
|
+
}), [
|
|
88
|
+
fullScreen,
|
|
89
|
+
currentImage?.src,
|
|
90
|
+
singleSlide,
|
|
91
|
+
isMobile,
|
|
92
|
+
swiper,
|
|
93
|
+
initialSlide,
|
|
94
|
+
setSwiper,
|
|
95
|
+
handleSlideChange,
|
|
96
|
+
]);
|
|
97
|
+
const showControls = !singleSlide && !fullScreen && !isMobile && !!images.length;
|
|
81
98
|
const swiperWidth = swiper?.width || 1;
|
|
82
99
|
const swiperHeight = swiper?.height || swiper?.width || 1;
|
|
83
100
|
const swiperAspectRatio = swiperWidth / swiperHeight;
|
|
84
|
-
const currentImage = getCurrentImage();
|
|
85
101
|
return (
|
|
86
102
|
/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */
|
|
87
|
-
React.createElement("div", { className: cn(styles.component, {
|
|
103
|
+
React.createElement("div", { className: cn(styles.component, {
|
|
104
|
+
[styles.singleSlide]: singleSlide,
|
|
105
|
+
[styles.mobile]: isMobile,
|
|
106
|
+
[styles.mobileVideo]: isMobile && isVideo(currentImage?.src),
|
|
107
|
+
}), onClick: handleWrapperClick },
|
|
88
108
|
showControls && (React.createElement("div", { className: cn(styles.arrow, {
|
|
89
109
|
[styles.focused]: leftArrowFocused,
|
|
90
110
|
}), 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 },
|
|
91
111
|
React.createElement(ChevronBackHeavyMIcon, null))),
|
|
92
|
-
fullScreen && (React.createElement("img", { src: currentImage?.src, alt: currentImage ? getImageAlt(currentImage, currentSlideIndex) : '', className: styles.fullScreenImage })),
|
|
112
|
+
fullScreen && !isVideo(currentImage?.src) && (React.createElement("img", { src: currentImage?.src, alt: currentImage ? getImageAlt(currentImage, currentSlideIndex) : '', className: styles.fullScreenImage })),
|
|
93
113
|
React.createElement(Swiper, { ...swiperProps }, images.map((image, index) => {
|
|
94
114
|
const meta = imagesMeta[index];
|
|
95
115
|
const imageWidth = meta?.width || 1;
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
display: flex;
|
|
5
5
|
flex-grow: 1;
|
|
6
6
|
justify-content: center;
|
|
7
|
-
align-items: center;
|
|
8
7
|
background-color: var(--color-static-neutral-0-inverted);
|
|
9
8
|
}
|
|
10
9
|
|
|
@@ -16,14 +15,31 @@
|
|
|
16
15
|
/* 168px - высота хэдера и футера */
|
|
17
16
|
max-height: calc(100vh - 168px);
|
|
18
17
|
padding: var(--gap-32) var(--gap-16);
|
|
19
|
-
box-sizing: border-box
|
|
18
|
+
box-sizing: border-box
|
|
20
19
|
}
|
|
21
20
|
|
|
21
|
+
.swiper.mobile {
|
|
22
|
+
max-height: calc(100vh - 210px);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.swiper.mobileVideo {
|
|
26
|
+
max-height: 100vh;
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
.singleSlide .swiper {
|
|
23
30
|
max-height: calc(100vh - 80px);
|
|
24
|
-
padding: var(--gap-32)
|
|
31
|
+
padding: var(--gap-32)
|
|
25
32
|
}
|
|
26
33
|
|
|
34
|
+
.singleSlide .swiper.mobile {
|
|
35
|
+
max-height: calc(100vh - 174px);
|
|
36
|
+
padding: 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.singleSlide .swiper.mobileVideo {
|
|
40
|
+
max-height: 100vh;
|
|
41
|
+
}
|
|
42
|
+
|
|
27
43
|
.hidden {
|
|
28
44
|
display: none;
|
|
29
45
|
}
|
|
@@ -47,17 +63,19 @@
|
|
|
47
63
|
height: 0;
|
|
48
64
|
-webkit-user-select: none;
|
|
49
65
|
user-select: none;
|
|
50
|
-
|
|
51
|
-
border-radius: var(--border-radius-8);
|
|
66
|
+
border-radius: var(--border-radius-8)
|
|
52
67
|
}
|
|
53
68
|
|
|
69
|
+
.image.mobile {
|
|
70
|
+
border-radius: var(--border-radius-0);
|
|
71
|
+
}
|
|
72
|
+
|
|
54
73
|
.smallImage {
|
|
55
74
|
position: relative;
|
|
56
75
|
width: auto;
|
|
57
76
|
height: auto;
|
|
58
77
|
-webkit-user-select: none;
|
|
59
78
|
user-select: none;
|
|
60
|
-
background-color: var(--color-light-base-bg-primary);
|
|
61
79
|
}
|
|
62
80
|
|
|
63
81
|
.verticalImageFit {
|
|
@@ -127,3 +145,8 @@
|
|
|
127
145
|
height: auto;
|
|
128
146
|
background-color: var(--color-light-base-bg-primary);
|
|
129
147
|
}
|
|
148
|
+
|
|
149
|
+
.fullScreenVideo {
|
|
150
|
+
width: calc(100% - 192px);
|
|
151
|
+
max-height: calc(100vh - 82px);
|
|
152
|
+
}
|