yet-another-react-lightbox 1.13.4 → 2.0.0-rc.3
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/dist/Lightbox.js +1 -1
- package/dist/core/components/IconButton.d.ts +1 -1
- package/dist/core/components/IconButton.js +3 -2
- package/dist/core/components/ImageSlide.js +15 -24
- package/dist/core/consts.d.ts +36 -0
- package/dist/core/consts.js +36 -0
- package/dist/core/contexts/Events.d.ts +5 -9
- package/dist/core/contexts/Events.js +23 -25
- package/dist/core/contexts/LightboxState.d.ts +20 -0
- package/dist/core/contexts/LightboxState.js +23 -0
- package/dist/core/contexts/Timeouts.d.ts +1 -2
- package/dist/core/contexts/Timeouts.js +26 -29
- package/dist/core/contexts/index.d.ts +1 -0
- package/dist/core/contexts/index.js +1 -0
- package/dist/core/hooks/index.d.ts +2 -1
- package/dist/core/hooks/index.js +2 -1
- package/dist/core/hooks/useEventCallback.d.ts +1 -0
- package/dist/core/hooks/useEventCallback.js +9 -0
- package/dist/core/hooks/useForkRef.d.ts +3 -0
- package/dist/core/hooks/useForkRef.js +15 -0
- package/dist/core/hooks/useMotionPreference.js +1 -2
- package/dist/core/hooks/useSensors.d.ts +4 -5
- package/dist/core/hooks/useSensors.js +9 -12
- package/dist/core/modules/Carousel.js +29 -31
- package/dist/core/modules/Controller.d.ts +3 -7
- package/dist/core/modules/Controller.js +144 -263
- package/dist/core/modules/Core.js +6 -4
- package/dist/core/modules/Navigation.js +16 -13
- package/dist/core/modules/NoScroll.js +4 -3
- package/dist/core/modules/Portal.js +51 -40
- package/dist/core/modules/Toolbar.js +6 -4
- package/dist/core/modules/controller/index.d.ts +8 -0
- package/dist/core/modules/controller/index.js +9 -0
- package/dist/core/modules/controller/useOffset.d.ts +2 -0
- package/dist/core/modules/controller/useOffset.js +10 -0
- package/dist/core/modules/controller/usePointerSwipe.d.ts +3 -0
- package/dist/core/modules/controller/usePointerSwipe.js +61 -0
- package/dist/core/modules/controller/usePreventSwipeNavigation.d.ts +3 -0
- package/dist/core/modules/controller/usePreventSwipeNavigation.js +20 -0
- package/dist/core/modules/controller/useWheelSwipe.d.ts +3 -0
- package/dist/core/modules/controller/useWheelSwipe.js +94 -0
- package/dist/core/utils.d.ts +12 -1
- package/dist/core/utils.js +14 -0
- package/dist/plugins/captions/Captions.d.ts +7 -0
- package/dist/plugins/captions/Captions.js +23 -0
- package/dist/plugins/captions/CaptionsContext.d.ts +8 -0
- package/dist/plugins/captions/CaptionsContext.js +15 -0
- package/dist/plugins/captions/Description.d.ts +5 -0
- package/dist/plugins/captions/Description.js +17 -0
- package/dist/plugins/captions/Title.d.ts +5 -0
- package/dist/plugins/captions/Title.js +9 -0
- package/dist/plugins/{captions.css → captions/captions.css} +0 -2
- package/dist/plugins/{Captions.d.ts → captions/index.d.ts} +3 -9
- package/dist/plugins/captions/index.js +2 -0
- package/dist/plugins/captions/utils.d.ts +1 -0
- package/dist/plugins/captions/utils.js +2 -0
- package/dist/plugins/fullscreen/Fullscreen.d.ts +3 -0
- package/dist/plugins/fullscreen/Fullscreen.js +17 -0
- package/dist/plugins/fullscreen/FullscreenButton.d.ts +8 -0
- package/dist/plugins/{Fullscreen.js → fullscreen/FullscreenButton.js} +16 -30
- package/dist/plugins/fullscreen/FullscreenContext.d.ts +5 -0
- package/dist/plugins/fullscreen/FullscreenContext.js +9 -0
- package/dist/plugins/{Fullscreen.d.ts → fullscreen/index.d.ts} +2 -11
- package/dist/plugins/fullscreen/index.js +2 -0
- package/dist/plugins/index.d.ts +7 -7
- package/dist/plugins/index.js +7 -7
- package/dist/plugins/inline/Inline.d.ts +3 -0
- package/dist/plugins/{Inline.js → inline/Inline.js} +5 -7
- package/dist/plugins/inline/index.d.ts +9 -0
- package/dist/plugins/inline/index.js +2 -0
- package/dist/plugins/slideshow/Slideshow.d.ts +7 -0
- package/dist/plugins/slideshow/Slideshow.js +20 -0
- package/dist/plugins/slideshow/SlideshowButton.d.ts +2 -0
- package/dist/plugins/{Slideshow.js → slideshow/SlideshowButton.js} +17 -44
- package/dist/plugins/{Slideshow.d.ts → slideshow/index.d.ts} +2 -4
- package/dist/plugins/slideshow/index.js +2 -0
- package/dist/plugins/thumbnails/Thumbnail.d.ts +21 -0
- package/dist/plugins/thumbnails/Thumbnail.js +45 -0
- package/dist/plugins/thumbnails/Thumbnails.d.ts +13 -0
- package/dist/plugins/thumbnails/Thumbnails.js +28 -0
- package/dist/plugins/thumbnails/ThumbnailsContainer.d.ts +3 -0
- package/dist/plugins/thumbnails/ThumbnailsContainer.js +14 -0
- package/dist/plugins/thumbnails/ThumbnailsTrack.d.ts +12 -0
- package/dist/plugins/thumbnails/ThumbnailsTrack.js +148 -0
- package/dist/plugins/{Thumbnails.d.ts → thumbnails/index.d.ts} +4 -16
- package/dist/plugins/thumbnails/index.js +2 -0
- package/dist/plugins/{thumbnails.css → thumbnails/thumbnails.css} +27 -37
- package/dist/plugins/thumbnails/utils.d.ts +2 -0
- package/dist/plugins/thumbnails/utils.js +4 -0
- package/dist/plugins/video/Video.d.ts +7 -0
- package/dist/plugins/video/Video.js +24 -0
- package/dist/plugins/video/VideoSlide.d.ts +9 -0
- package/dist/plugins/{Video.js → video/VideoSlide.js} +14 -39
- package/dist/plugins/{Video.d.ts → video/index.d.ts} +5 -13
- package/dist/plugins/video/index.js +2 -0
- package/dist/plugins/zoom/Zoom.d.ts +14 -0
- package/dist/plugins/zoom/Zoom.js +36 -0
- package/dist/plugins/zoom/ZoomButton.d.ts +7 -0
- package/dist/plugins/zoom/ZoomButton.js +50 -0
- package/dist/plugins/zoom/ZoomButtonsGroup.d.ts +5 -0
- package/dist/plugins/zoom/ZoomButtonsGroup.js +23 -0
- package/dist/plugins/zoom/ZoomContainer.d.ts +9 -0
- package/dist/plugins/zoom/ZoomContainer.js +303 -0
- package/dist/plugins/zoom/ZoomContext.d.ts +12 -0
- package/dist/plugins/zoom/ZoomContext.js +18 -0
- package/dist/plugins/zoom/ZoomWrapper.d.ts +3 -0
- package/dist/plugins/zoom/ZoomWrapper.js +26 -0
- package/dist/plugins/{Zoom.d.ts → zoom/index.d.ts} +5 -5
- package/dist/plugins/zoom/index.js +4 -0
- package/dist/props.d.ts +2 -0
- package/dist/props.js +31 -0
- package/dist/styles.css +33 -27
- package/dist/types.d.ts +8 -22
- package/dist/types.js +1 -30
- package/package.json +17 -17
- package/dist/core/hooks/useLatest.d.ts +0 -3
- package/dist/core/hooks/useLatest.js +0 -6
- package/dist/plugins/Captions.js +0 -58
- package/dist/plugins/Inline.d.ts +0 -15
- package/dist/plugins/Thumbnails.js +0 -243
- package/dist/plugins/Zoom.js +0 -441
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { ACTION_NEXT, ACTION_PREV, CLASS_FLEX_CENTER, clsx, cssClass, cssVar, useEventCallback, useEvents, useLayoutEffect, useLightboxState, useMotionPreference, useRTL, } from "../../core/index.js";
|
|
3
|
+
import { cssPrefix, cssThumbnailPrefix } from "./utils.js";
|
|
4
|
+
import { Thumbnail } from "./Thumbnail.js";
|
|
5
|
+
import { defaultThumbnailsProps } from "./Thumbnails.js";
|
|
6
|
+
const isHorizontal = (position) => ["top", "bottom"].includes(position);
|
|
7
|
+
const boxSize = (thumbnails, dimension, includeGap) => dimension + 2 * (thumbnails.border + thumbnails.padding) + (includeGap ? thumbnails.gap : 0);
|
|
8
|
+
const getSlide = (slides, index) => slides[((index % slides.length) + slides.length) % slides.length];
|
|
9
|
+
export const ThumbnailsTrack = ({ container, startingIndex, slides, carousel, render, thumbnails, thumbnailRect, styles, }) => {
|
|
10
|
+
const [index, setIndex] = React.useState(startingIndex);
|
|
11
|
+
const [offset, setOffset] = React.useState(0);
|
|
12
|
+
const track = React.useRef(null);
|
|
13
|
+
const animationRef = React.useRef();
|
|
14
|
+
const animationOffset = React.useRef(0);
|
|
15
|
+
const { state: { globalIndex, animationDuration }, } = useLightboxState();
|
|
16
|
+
const { publish } = useEvents();
|
|
17
|
+
const reduceMotion = useMotionPreference();
|
|
18
|
+
const isRTL = useRTL();
|
|
19
|
+
const handleControllerSwipe = useEventCallback(() => {
|
|
20
|
+
if (container.current && track.current) {
|
|
21
|
+
const containerRect = container.current.getBoundingClientRect();
|
|
22
|
+
const trackRect = track.current.getBoundingClientRect();
|
|
23
|
+
animationOffset.current = isHorizontal(thumbnails.position)
|
|
24
|
+
? trackRect.left - (containerRect.width - trackRect.width) / 2
|
|
25
|
+
: trackRect.top - (containerRect.height - trackRect.height) / 2;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
animationOffset.current = 0;
|
|
29
|
+
}
|
|
30
|
+
setIndex(globalIndex);
|
|
31
|
+
setOffset(globalIndex - index);
|
|
32
|
+
});
|
|
33
|
+
React.useEffect(handleControllerSwipe, [globalIndex, handleControllerSwipe]);
|
|
34
|
+
const getCurrentIndex = useEventCallback(() => index);
|
|
35
|
+
const handleIndexOffsetChange = useEventCallback(() => {
|
|
36
|
+
var _a, _b, _c;
|
|
37
|
+
if (track.current && offset) {
|
|
38
|
+
(_a = animationRef.current) === null || _a === void 0 ? void 0 : _a.cancel();
|
|
39
|
+
animationRef.current = (_c = (_b = track.current).animate) === null || _c === void 0 ? void 0 : _c.call(_b, isHorizontal(thumbnails.position)
|
|
40
|
+
? [
|
|
41
|
+
{
|
|
42
|
+
transform: `translateX(${(isRTL ? -1 : 1) * boxSize(thumbnails, thumbnails.width, true) * offset +
|
|
43
|
+
animationOffset.current}px)`,
|
|
44
|
+
},
|
|
45
|
+
{ transform: "translateX(0)" },
|
|
46
|
+
]
|
|
47
|
+
: [
|
|
48
|
+
{
|
|
49
|
+
transform: `translateY(${boxSize(thumbnails, thumbnails.height, true) * offset + animationOffset.current}px)`,
|
|
50
|
+
},
|
|
51
|
+
{ transform: "translateY(0)" },
|
|
52
|
+
], !reduceMotion ? animationDuration : 0);
|
|
53
|
+
if (animationRef.current) {
|
|
54
|
+
animationRef.current.onfinish = () => {
|
|
55
|
+
animationRef.current = undefined;
|
|
56
|
+
if (getCurrentIndex() === index) {
|
|
57
|
+
setOffset(0);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
animationOffset.current = 0;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
useLayoutEffect(handleIndexOffsetChange, [index, offset, handleIndexOffsetChange]);
|
|
65
|
+
const { finite, preload } = carousel;
|
|
66
|
+
const items = [];
|
|
67
|
+
if (slides.length > 0) {
|
|
68
|
+
if (offset < 0) {
|
|
69
|
+
for (let i = index - preload + offset; i < index - preload; i += 1) {
|
|
70
|
+
items.push({ slide: null, index: i, placeholder: true });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (let i = index - preload - (offset > 0 ? offset : 0); i < index; i += 1) {
|
|
74
|
+
if (!(finite && i < 0)) {
|
|
75
|
+
items.push({ slide: getSlide(slides, i), index: i });
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
items.push({ slide: null, index: i, placeholder: true });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
items.push({ slide: getSlide(slides, index), index });
|
|
82
|
+
for (let i = index + 1; i <= index + preload - (offset < 0 ? offset : 0); i += 1) {
|
|
83
|
+
if (!finite || i <= slides.length - 1) {
|
|
84
|
+
items.push({ slide: getSlide(slides, i), index: i });
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
items.push({ slide: null, index: i, placeholder: true });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (offset > 0) {
|
|
91
|
+
for (let i = index + preload + 1; i <= index + preload + offset; i += 1) {
|
|
92
|
+
items.push({ slide: null, index: i, placeholder: true });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const handleClick = (slideIndex) => () => {
|
|
97
|
+
if (slideIndex > index) {
|
|
98
|
+
publish(ACTION_NEXT, slideIndex - index);
|
|
99
|
+
}
|
|
100
|
+
else if (slideIndex < index) {
|
|
101
|
+
publish(ACTION_PREV, index - slideIndex);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
const { width, height, border, borderRadius, padding, gap, imageFit } = thumbnails;
|
|
105
|
+
return (React.createElement("div", { className: clsx(cssClass(cssPrefix("container")), cssClass(CLASS_FLEX_CENTER)), style: {
|
|
106
|
+
...(width !== defaultThumbnailsProps.width
|
|
107
|
+
? { [cssVar(cssThumbnailPrefix("width"))]: `${boxSize(thumbnails, width)}px` }
|
|
108
|
+
: null),
|
|
109
|
+
...(height !== defaultThumbnailsProps.height
|
|
110
|
+
? { [cssVar(cssThumbnailPrefix("height"))]: `${boxSize(thumbnails, height)}px` }
|
|
111
|
+
: null),
|
|
112
|
+
...(border !== defaultThumbnailsProps.border
|
|
113
|
+
? { [cssVar(cssThumbnailPrefix("border"))]: `${border}px` }
|
|
114
|
+
: null),
|
|
115
|
+
...(borderRadius !== defaultThumbnailsProps.borderRadius
|
|
116
|
+
? { [cssVar(cssThumbnailPrefix("border_radius"))]: `${borderRadius}px` }
|
|
117
|
+
: null),
|
|
118
|
+
...(padding !== defaultThumbnailsProps.padding
|
|
119
|
+
? { [cssVar(cssThumbnailPrefix("padding"))]: `${padding}px` }
|
|
120
|
+
: null),
|
|
121
|
+
...(gap !== defaultThumbnailsProps.gap ? { [cssVar(cssThumbnailPrefix("gap"))]: `${gap}px` } : null),
|
|
122
|
+
...styles.thumbnailsContainer,
|
|
123
|
+
} },
|
|
124
|
+
React.createElement("nav", { ref: track, style: styles.thumbnailsTrack, className: clsx(cssClass(cssPrefix("track")), cssClass(CLASS_FLEX_CENTER)) }, items.map(({ slide, index: slideIndex, placeholder }) => {
|
|
125
|
+
const fadeAnimationDuration = animationDuration / Math.abs(offset || 1);
|
|
126
|
+
const fadeIn = (offset > 0 && slideIndex > index + preload - offset && slideIndex <= index + preload) ||
|
|
127
|
+
(offset < 0 && slideIndex < index - preload - offset && slideIndex >= index - preload)
|
|
128
|
+
? {
|
|
129
|
+
duration: fadeAnimationDuration,
|
|
130
|
+
delay: ((offset > 0
|
|
131
|
+
? slideIndex - (index + preload - offset)
|
|
132
|
+
: index - preload - offset - slideIndex) -
|
|
133
|
+
1) *
|
|
134
|
+
fadeAnimationDuration,
|
|
135
|
+
}
|
|
136
|
+
: undefined;
|
|
137
|
+
const fadeOut = (offset > 0 && slideIndex < index - preload) || (offset < 0 && slideIndex > index + preload)
|
|
138
|
+
? {
|
|
139
|
+
duration: fadeAnimationDuration,
|
|
140
|
+
delay: (offset > 0
|
|
141
|
+
? offset - (index - preload - slideIndex)
|
|
142
|
+
: -offset - (slideIndex - (index + preload))) * fadeAnimationDuration,
|
|
143
|
+
}
|
|
144
|
+
: undefined;
|
|
145
|
+
return (React.createElement(Thumbnail, { key: slideIndex, rect: thumbnailRect, slide: slide, imageFit: imageFit, render: render, active: slideIndex === index, fadeIn: fadeIn, fadeOut: fadeOut, placeholder: Boolean(placeholder), onClick: handleClick(slideIndex), style: styles.thumbnail }));
|
|
146
|
+
})),
|
|
147
|
+
React.createElement("div", { className: cssClass(cssPrefix("vignette")) })));
|
|
148
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
declare module "
|
|
2
|
+
import { ContainerRect } from "../../core/index.js";
|
|
3
|
+
import { Thumbnails } from "./Thumbnails.js";
|
|
4
|
+
declare type Position = "top" | "bottom" | "start" | "end";
|
|
5
|
+
declare module "../../types" {
|
|
6
6
|
interface LightboxProps {
|
|
7
7
|
/** Thumbnails plugin settings */
|
|
8
8
|
thumbnails?: {
|
|
@@ -41,16 +41,4 @@ declare module "../types.js" {
|
|
|
41
41
|
thumbnailsContainer: "thumbnailsContainer";
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
declare type ThumbnailsInternal = DeepNonNullable<LightboxProps["thumbnails"]>;
|
|
45
|
-
declare type ThumbnailsTrackProps = Pick<LightboxProps, "slides" | "carousel" | "animation" | "render" | "styles"> & {
|
|
46
|
-
container: React.RefObject<HTMLDivElement>;
|
|
47
|
-
thumbnails: ThumbnailsInternal;
|
|
48
|
-
startingIndex: number;
|
|
49
|
-
thumbnailRect: ContainerRect;
|
|
50
|
-
};
|
|
51
|
-
export declare const ThumbnailsTrack: React.FC<ThumbnailsTrackProps>;
|
|
52
|
-
/** Thumbnails plugin component */
|
|
53
|
-
export declare const ThumbnailsComponent: Component;
|
|
54
|
-
/** Thumbnails plugin */
|
|
55
|
-
export declare const Thumbnails: Plugin;
|
|
56
44
|
export default Thumbnails;
|
|
@@ -1,69 +1,60 @@
|
|
|
1
1
|
.yarl__thumbnails {
|
|
2
2
|
display: flex;
|
|
3
|
+
height: 100%;
|
|
3
4
|
}
|
|
4
5
|
.yarl__thumbnails_top, .yarl__thumbnails_bottom {
|
|
5
|
-
flex-
|
|
6
|
-
}
|
|
7
|
-
.yarl__thumbnails_top .yarl__thumbnails_track, .yarl__thumbnails_bottom .yarl__thumbnails_track {
|
|
8
|
-
flex-flow: row nowrap;
|
|
9
|
-
}
|
|
10
|
-
.yarl__thumbnails_start, .yarl__thumbnails_end {
|
|
11
|
-
flex-flow: row nowrap;
|
|
6
|
+
flex-direction: column;
|
|
12
7
|
}
|
|
13
8
|
.yarl__thumbnails_start .yarl__thumbnails_track, .yarl__thumbnails_end .yarl__thumbnails_track {
|
|
14
|
-
flex-
|
|
9
|
+
flex-direction: column;
|
|
15
10
|
}
|
|
16
11
|
.yarl__thumbnails_wrapper {
|
|
17
|
-
flex
|
|
12
|
+
flex: 1;
|
|
18
13
|
position: relative;
|
|
19
14
|
}
|
|
20
15
|
.yarl__thumbnails_container {
|
|
16
|
+
flex: 0 0 auto;
|
|
21
17
|
background-color: var(--yarl__thumbnails_container_background_color, var(--yarl__color_backdrop, #000));
|
|
22
18
|
padding: var(--yarl__thumbnails_container_padding, 16px);
|
|
23
19
|
position: relative;
|
|
24
20
|
overflow: hidden;
|
|
25
|
-
z-index: 0;
|
|
26
21
|
-webkit-user-select: none;
|
|
27
22
|
-moz-user-select: none;
|
|
28
23
|
user-select: none;
|
|
29
24
|
-webkit-touch-callout: none;
|
|
30
25
|
}
|
|
31
|
-
.
|
|
32
|
-
content: "";
|
|
26
|
+
.yarl__thumbnails_vignette {
|
|
33
27
|
position: absolute;
|
|
34
|
-
|
|
28
|
+
pointer-events: none;
|
|
29
|
+
--yarl__thumbnails_vignette_size: 12%;
|
|
35
30
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
@media (min-width: 1200px) {
|
|
32
|
+
.yarl__thumbnails_vignette {
|
|
33
|
+
--yarl__thumbnails_vignette_size: 8%;
|
|
34
|
+
}
|
|
39
35
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
@media (min-width: 2000px) {
|
|
37
|
+
.yarl__thumbnails_vignette {
|
|
38
|
+
--yarl__thumbnails_vignette_size: 5%;
|
|
39
|
+
}
|
|
43
40
|
}
|
|
44
|
-
.yarl__thumbnails_top .
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
.yarl__thumbnails_top .yarl__thumbnails_vignette, .yarl__thumbnails_bottom .yarl__thumbnails_vignette {
|
|
42
|
+
height: 100%;
|
|
43
|
+
left: 0;
|
|
44
|
+
right: 0;
|
|
45
|
+
background: linear-gradient(to right, var(--yarl__color_backdrop, #000) 0px, transparent var(--yarl__thumbnails_vignette_size, 12%) calc(100% - var(--yarl__thumbnails_vignette_size, 12%)), var(--yarl__color_backdrop, #000) 100%);
|
|
48
46
|
}
|
|
49
|
-
.yarl__thumbnails_start .
|
|
47
|
+
.yarl__thumbnails_start .yarl__thumbnails_vignette, .yarl__thumbnails_end .yarl__thumbnails_vignette {
|
|
48
|
+
width: 100%;
|
|
50
49
|
top: 0;
|
|
51
|
-
background: linear-gradient(to top, transparent, var(--yarl__color_backdrop, #000));
|
|
52
|
-
}
|
|
53
|
-
.yarl__thumbnails_start .yarl__thumbnails_container::after, .yarl__thumbnails_end .yarl__thumbnails_container::after {
|
|
54
50
|
bottom: 0;
|
|
55
|
-
background: linear-gradient(to bottom, transparent, var(--yarl__color_backdrop, #000));
|
|
56
|
-
}
|
|
57
|
-
.yarl__thumbnails_start .yarl__thumbnails_container::before, .yarl__thumbnails_start .yarl__thumbnails_container::after, .yarl__thumbnails_end .yarl__thumbnails_container::before, .yarl__thumbnails_end .yarl__thumbnails_container::after {
|
|
58
|
-
left: 0;
|
|
59
|
-
right: 0;
|
|
60
|
-
height: 60px;
|
|
51
|
+
background: linear-gradient(to bottom, var(--yarl__color_backdrop, #000) 0px, transparent var(--yarl__thumbnails_vignette_size, 12%) calc(100% - var(--yarl__thumbnails_vignette_size, 12%)), var(--yarl__color_backdrop, #000) 100%);
|
|
61
52
|
}
|
|
62
53
|
.yarl__thumbnails_track {
|
|
63
|
-
display: flex;
|
|
64
54
|
gap: var(--yarl__thumbnails_thumbnail_gap, 16px);
|
|
65
55
|
}
|
|
66
56
|
.yarl__thumbnails_thumbnail {
|
|
57
|
+
flex: 0 0 auto;
|
|
67
58
|
cursor: pointer;
|
|
68
59
|
-webkit-appearance: none;
|
|
69
60
|
-moz-appearance: none;
|
|
@@ -72,7 +63,6 @@
|
|
|
72
63
|
border: var(--yarl__thumbnails_thumbnail_border, 1px solid var(--yarl__color_button, rgba(255, 255, 255, 0.8)));
|
|
73
64
|
border-radius: var(--yarl__thumbnails_thumbnail_border_radius, 4px);
|
|
74
65
|
-webkit-tap-highlight-color: transparent;
|
|
75
|
-
flex-shrink: 0;
|
|
76
66
|
position: relative;
|
|
77
67
|
overflow: hidden;
|
|
78
68
|
padding: var(--yarl__thumbnails_thumbnail_padding, 4px);
|
|
@@ -104,8 +94,8 @@
|
|
|
104
94
|
position: absolute;
|
|
105
95
|
top: 50%;
|
|
106
96
|
left: 50%;
|
|
107
|
-
-webkit-transform:
|
|
108
|
-
transform:
|
|
97
|
+
-webkit-transform: translateX(-50%) translateY(-50%);
|
|
98
|
+
transform: translateX(-50%) translateY(-50%);
|
|
109
99
|
width: var(--yarl__thumbnails_thumbnail_icon_size, 32px);
|
|
110
100
|
height: var(--yarl__thumbnails_thumbnail_icon_size, 32px);
|
|
111
101
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { composePrefix } from "../../core/utils.js";
|
|
2
|
+
import { PLUGIN_THUMBNAILS } from "../../core/consts.js";
|
|
3
|
+
export const cssPrefix = (value) => composePrefix(PLUGIN_THUMBNAILS, value);
|
|
4
|
+
export const cssThumbnailPrefix = (value) => cssPrefix(composePrefix("thumbnail", value));
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { VideoSlide } from "./VideoSlide.js";
|
|
3
|
+
export const defaultVideoProps = {
|
|
4
|
+
controls: true,
|
|
5
|
+
playsInline: true,
|
|
6
|
+
};
|
|
7
|
+
export const Video = ({ augment }) => {
|
|
8
|
+
augment(({ render: { slide: renderSlide, ...restRender }, video: originalVideo, ...restProps }) => ({
|
|
9
|
+
render: {
|
|
10
|
+
slide: (slide, offset, rect) => {
|
|
11
|
+
if (slide.type === "video") {
|
|
12
|
+
return React.createElement(VideoSlide, { slide: slide, offset: offset });
|
|
13
|
+
}
|
|
14
|
+
return renderSlide === null || renderSlide === void 0 ? void 0 : renderSlide(slide, offset, rect);
|
|
15
|
+
},
|
|
16
|
+
...restRender,
|
|
17
|
+
},
|
|
18
|
+
video: {
|
|
19
|
+
...defaultVideoProps,
|
|
20
|
+
...originalVideo,
|
|
21
|
+
},
|
|
22
|
+
...restProps,
|
|
23
|
+
}));
|
|
24
|
+
};
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { ACTIVE_SLIDE_COMPLETE, ACTIVE_SLIDE_LOADING, ACTIVE_SLIDE_PLAYING, clsx, cssClass, useContainerRect, useController,
|
|
3
|
-
|
|
4
|
-
controls: true,
|
|
5
|
-
playsInline: true,
|
|
6
|
-
};
|
|
2
|
+
import { ACTIVE_SLIDE_COMPLETE, ACTIVE_SLIDE_LOADING, ACTIVE_SLIDE_PLAYING, CLASS_FLEX_CENTER, clsx, cssClass, useContainerRect, useController, useEventCallback, useEvents, } from "../../core/index.js";
|
|
3
|
+
import { defaultVideoProps } from "./Video.js";
|
|
7
4
|
export const VideoSlide = ({ slide, offset }) => {
|
|
8
|
-
var _a;
|
|
9
|
-
const { latestProps } = useController();
|
|
10
5
|
const { publish } = useEvents();
|
|
11
6
|
const { setContainerRef, containerRect } = useContainerRect();
|
|
12
7
|
const videoRef = React.useRef(null);
|
|
13
|
-
const video =
|
|
8
|
+
const video = { ...defaultVideoProps, ...useController().getLightboxProps().video };
|
|
14
9
|
React.useEffect(() => {
|
|
15
10
|
if (offset !== 0 && videoRef.current && !videoRef.current.paused) {
|
|
16
11
|
videoRef.current.pause();
|
|
@@ -22,18 +17,17 @@ export const VideoSlide = ({ slide, offset }) => {
|
|
|
22
17
|
videoRef.current.play().catch(() => { });
|
|
23
18
|
}
|
|
24
19
|
}, [offset, video.autoPlay, slide.autoPlay, publish]);
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
el.play().catch(() => { });
|
|
20
|
+
const handleVideoRef = useEventCallback((node) => {
|
|
21
|
+
if (offset === 0 && (video.autoPlay || slide.autoPlay) && node.paused) {
|
|
22
|
+
node.play().catch(() => { });
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const setVideoRef = React.useCallback((node) => {
|
|
26
|
+
videoRef.current = node;
|
|
27
|
+
if (node) {
|
|
28
|
+
handleVideoRef(node);
|
|
35
29
|
}
|
|
36
|
-
}, [
|
|
30
|
+
}, [handleVideoRef]);
|
|
37
31
|
const { width, height, poster, sources } = slide;
|
|
38
32
|
const scaleWidthAndHeight = () => {
|
|
39
33
|
if (!width || !height || !containerRect)
|
|
@@ -68,28 +62,9 @@ export const VideoSlide = ({ slide, offset }) => {
|
|
|
68
62
|
width: "100%",
|
|
69
63
|
height: "100%",
|
|
70
64
|
...(width ? { maxWidth: `${width}px` } : null),
|
|
71
|
-
}, className: clsx(cssClass("video_container"), cssClass(
|
|
65
|
+
}, className: clsx(cssClass("video_container"), cssClass(CLASS_FLEX_CENTER)) }, containerRect && (React.createElement("video", { ref: setVideoRef, poster: poster, ...scaleWidthAndHeight(), ...resolveBoolean("controls"), ...resolveBoolean("playsInline"), ...resolveBoolean("loop"), ...resolveBoolean("muted"), ...resolveBoolean("playsInline"), ...resolveBoolean("disablePictureInPicture"), ...resolveBoolean("disableRemotePlayback"), ...resolveString("controlsList"), ...resolveString("crossOrigin"), ...resolveString("preload"), onPlay: () => {
|
|
72
66
|
publish(ACTIVE_SLIDE_PLAYING);
|
|
73
67
|
}, onEnded: () => {
|
|
74
68
|
publish(ACTIVE_SLIDE_COMPLETE);
|
|
75
69
|
} }, sources.map(({ src, type }, index) => (React.createElement("source", { key: index, src: src, type: type })))))))));
|
|
76
70
|
};
|
|
77
|
-
export const Video = ({ augment }) => {
|
|
78
|
-
augment(({ render: { slide: renderSlide, ...restRender }, video: originalVideo, ...restProps }) => ({
|
|
79
|
-
render: {
|
|
80
|
-
slide: (slide, offset, rect) => {
|
|
81
|
-
if ("type" in slide && slide.type === "video") {
|
|
82
|
-
return React.createElement(VideoSlide, { slide: slide, offset: offset });
|
|
83
|
-
}
|
|
84
|
-
return renderSlide === null || renderSlide === void 0 ? void 0 : renderSlide(slide, offset, rect);
|
|
85
|
-
},
|
|
86
|
-
...restRender,
|
|
87
|
-
},
|
|
88
|
-
video: {
|
|
89
|
-
...defaultVideoProps,
|
|
90
|
-
...originalVideo,
|
|
91
|
-
},
|
|
92
|
-
...restProps,
|
|
93
|
-
}));
|
|
94
|
-
};
|
|
95
|
-
export default Video;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { GenericSlide } from "../../types.js";
|
|
2
|
+
import { Video } from "./Video.js";
|
|
3
3
|
/** Video slide attributes */
|
|
4
|
-
export interface SlideVideo {
|
|
4
|
+
export interface SlideVideo extends GenericSlide {
|
|
5
5
|
/** video slide type marker */
|
|
6
6
|
type: "video";
|
|
7
7
|
/** video placeholder image */
|
|
@@ -31,14 +31,14 @@ export interface SlideVideo {
|
|
|
31
31
|
/** disables the capability of remote playback */
|
|
32
32
|
disableRemotePlayback?: boolean;
|
|
33
33
|
/** an array of video files */
|
|
34
|
-
sources
|
|
34
|
+
sources: {
|
|
35
35
|
/** video source URL */
|
|
36
36
|
src: string;
|
|
37
37
|
/** video source type (e.g., `video/mp4`) */
|
|
38
38
|
type: string;
|
|
39
39
|
}[];
|
|
40
40
|
}
|
|
41
|
-
declare module "
|
|
41
|
+
declare module "../../types" {
|
|
42
42
|
interface SlideTypes {
|
|
43
43
|
/** video slide type */
|
|
44
44
|
SlideVideo: SlideVideo;
|
|
@@ -48,12 +48,4 @@ declare module "../types.js" {
|
|
|
48
48
|
video?: Pick<SlideVideo, "autoPlay" | "controls" | "controlsList" | "crossOrigin" | "preload" | "loop" | "muted" | "playsInline" | "disablePictureInPicture" | "disableRemotePlayback">;
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
-
declare type VideoSlideProps = {
|
|
52
|
-
slide: SlideVideo;
|
|
53
|
-
offset: number;
|
|
54
|
-
};
|
|
55
|
-
/** Video slide */
|
|
56
|
-
export declare const VideoSlide: React.FC<VideoSlideProps>;
|
|
57
|
-
/** Video plugin */
|
|
58
|
-
export declare const Video: Plugin;
|
|
59
51
|
export default Video;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Plugin } from "../../types.js";
|
|
2
|
+
export declare const defaultZoomProps: {
|
|
3
|
+
maxZoomPixelRatio: number;
|
|
4
|
+
zoomInMultiplier: number;
|
|
5
|
+
doubleTapDelay: number;
|
|
6
|
+
doubleClickDelay: number;
|
|
7
|
+
doubleClickMaxStops: number;
|
|
8
|
+
keyboardMoveDistance: number;
|
|
9
|
+
wheelZoomDistanceFactor: number;
|
|
10
|
+
pinchZoomDistanceFactor: number;
|
|
11
|
+
scrollToZoom: boolean;
|
|
12
|
+
};
|
|
13
|
+
/** Zoom plugin */
|
|
14
|
+
export declare const Zoom: Plugin;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { createModule, MODULE_CONTROLLER, PLUGIN_ZOOM } from "../../core/index.js";
|
|
3
|
+
import { ZoomContextProvider } from "./ZoomContext.js";
|
|
4
|
+
import { ZoomButtonsGroup } from "./ZoomButtonsGroup.js";
|
|
5
|
+
import { ZoomWrapper } from "./ZoomWrapper.js";
|
|
6
|
+
export const defaultZoomProps = {
|
|
7
|
+
maxZoomPixelRatio: 1,
|
|
8
|
+
zoomInMultiplier: 2,
|
|
9
|
+
doubleTapDelay: 300,
|
|
10
|
+
doubleClickDelay: 500,
|
|
11
|
+
doubleClickMaxStops: 2,
|
|
12
|
+
keyboardMoveDistance: 50,
|
|
13
|
+
wheelZoomDistanceFactor: 100,
|
|
14
|
+
pinchZoomDistanceFactor: 100,
|
|
15
|
+
scrollToZoom: false,
|
|
16
|
+
};
|
|
17
|
+
export const Zoom = ({ augment, append }) => {
|
|
18
|
+
augment(({ toolbar: { buttons, ...restToolbar }, render, carousel, animation, zoom, ...restProps }) => ({
|
|
19
|
+
toolbar: {
|
|
20
|
+
buttons: [React.createElement(ZoomButtonsGroup, { key: PLUGIN_ZOOM, labels: restProps.labels, render: render }), ...buttons],
|
|
21
|
+
...restToolbar,
|
|
22
|
+
},
|
|
23
|
+
render: {
|
|
24
|
+
...render,
|
|
25
|
+
slide: (slide, offset, rect) => (React.createElement(ZoomWrapper, { slide: slide, offset: offset, rect: rect, render: render, carousel: carousel, animation: animation, zoom: zoom })),
|
|
26
|
+
},
|
|
27
|
+
zoom: {
|
|
28
|
+
...defaultZoomProps,
|
|
29
|
+
...zoom,
|
|
30
|
+
},
|
|
31
|
+
carousel,
|
|
32
|
+
animation,
|
|
33
|
+
...restProps,
|
|
34
|
+
}));
|
|
35
|
+
append(MODULE_CONTROLLER, createModule(PLUGIN_ZOOM, ZoomContextProvider));
|
|
36
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { LightboxProps } from "../../types.js";
|
|
3
|
+
/** Zoom button */
|
|
4
|
+
export declare const ZoomButton: React.ForwardRefExoticComponent<Pick<LightboxProps, "render" | "labels"> & {
|
|
5
|
+
zoomIn?: boolean | undefined;
|
|
6
|
+
onLoseFocus: () => void;
|
|
7
|
+
} & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { createIcon, IconButton, label, useEvents } from "../../core/index.js";
|
|
3
|
+
import { useZoom } from "./ZoomContext.js";
|
|
4
|
+
import { ACTION_ZOOM_IN, ACTION_ZOOM_OUT } from "./index.js";
|
|
5
|
+
const ZoomInIcon = createIcon("ZoomIn", React.createElement(React.Fragment, null,
|
|
6
|
+
React.createElement("path", { d: "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" }),
|
|
7
|
+
React.createElement("path", { d: "M12 10h-2v2H9v-2H7V9h2V7h1v2h2v1z" })));
|
|
8
|
+
const ZoomOutIcon = createIcon("ZoomOut", React.createElement("path", { d: "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14zM7 9h5v1H7z" }));
|
|
9
|
+
export const ZoomButton = React.forwardRef(({ labels, render, zoomIn, onLoseFocus }, ref) => {
|
|
10
|
+
const wasEnabled = React.useRef(false);
|
|
11
|
+
const wasFocused = React.useRef(false);
|
|
12
|
+
const { isMinZoom, isMaxZoom, isZoomSupported } = useZoom();
|
|
13
|
+
const { publish } = useEvents();
|
|
14
|
+
const disabled = !isZoomSupported || (zoomIn ? isMaxZoom : isMinZoom);
|
|
15
|
+
const onClick = () => publish(zoomIn ? ACTION_ZOOM_IN : ACTION_ZOOM_OUT);
|
|
16
|
+
const onFocus = React.useCallback(() => {
|
|
17
|
+
wasFocused.current = true;
|
|
18
|
+
}, []);
|
|
19
|
+
const onBlur = React.useCallback(() => {
|
|
20
|
+
wasFocused.current = false;
|
|
21
|
+
}, []);
|
|
22
|
+
React.useEffect(() => {
|
|
23
|
+
if (disabled && wasEnabled.current && wasFocused.current) {
|
|
24
|
+
onLoseFocus();
|
|
25
|
+
}
|
|
26
|
+
if (!disabled) {
|
|
27
|
+
wasEnabled.current = true;
|
|
28
|
+
}
|
|
29
|
+
}, [disabled, onLoseFocus]);
|
|
30
|
+
if (zoomIn && render.buttonZoomIn)
|
|
31
|
+
return (React.createElement(React.Fragment, null, render.buttonZoomIn({
|
|
32
|
+
ref,
|
|
33
|
+
labels,
|
|
34
|
+
disabled,
|
|
35
|
+
onClick,
|
|
36
|
+
onFocus,
|
|
37
|
+
onBlur,
|
|
38
|
+
})));
|
|
39
|
+
if (!zoomIn && render.buttonZoomOut)
|
|
40
|
+
return (React.createElement(React.Fragment, null, render.buttonZoomOut({
|
|
41
|
+
ref,
|
|
42
|
+
labels,
|
|
43
|
+
disabled,
|
|
44
|
+
onClick,
|
|
45
|
+
onFocus,
|
|
46
|
+
onBlur,
|
|
47
|
+
})));
|
|
48
|
+
return (React.createElement(IconButton, { ref: ref, label: label(labels, zoomIn ? "Zoom in" : "Zoom out"), icon: zoomIn ? ZoomInIcon : ZoomOutIcon, renderIcon: zoomIn ? render.iconZoomIn : render.iconZoomOut, disabled: disabled, onClick: onClick, onFocus: onFocus, onBlur: onBlur }));
|
|
49
|
+
});
|
|
50
|
+
ZoomButton.displayName = "ZoomButton";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { useController } from "../../core/index.js";
|
|
3
|
+
import { ZoomButton } from "./ZoomButton.js";
|
|
4
|
+
import { ACTION_ZOOM_IN, ACTION_ZOOM_OUT } from "./index.js";
|
|
5
|
+
export const ZoomButtonsGroup = ({ labels, render }) => {
|
|
6
|
+
const zoomInRef = React.useRef(null);
|
|
7
|
+
const zoomOutRef = React.useRef(null);
|
|
8
|
+
const { transferFocus } = useController();
|
|
9
|
+
const focusSibling = React.useCallback((sibling) => {
|
|
10
|
+
var _a, _b;
|
|
11
|
+
if (!((_a = sibling.current) === null || _a === void 0 ? void 0 : _a.disabled)) {
|
|
12
|
+
(_b = sibling.current) === null || _b === void 0 ? void 0 : _b.focus();
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
transferFocus();
|
|
16
|
+
}
|
|
17
|
+
}, [transferFocus]);
|
|
18
|
+
const focusZoomIn = React.useCallback(() => focusSibling(zoomInRef), [focusSibling]);
|
|
19
|
+
const focusZoomOut = React.useCallback(() => focusSibling(zoomOutRef), [focusSibling]);
|
|
20
|
+
return (React.createElement(React.Fragment, null,
|
|
21
|
+
React.createElement(ZoomButton, { ref: zoomInRef, key: ACTION_ZOOM_IN, zoomIn: true, labels: labels, render: render, onLoseFocus: focusZoomOut }),
|
|
22
|
+
React.createElement(ZoomButton, { ref: zoomOutRef, key: ACTION_ZOOM_OUT, labels: labels, render: render, onLoseFocus: focusZoomIn })));
|
|
23
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { ContainerRect } from "../../core/index.js";
|
|
3
|
+
import { LightboxProps, Slide } from "../../types.js";
|
|
4
|
+
/** Zoom container */
|
|
5
|
+
export declare const ZoomContainer: React.FC<Pick<LightboxProps, "render" | "carousel" | "zoom" | "animation"> & {
|
|
6
|
+
slide: Slide;
|
|
7
|
+
offset: number;
|
|
8
|
+
rect: ContainerRect;
|
|
9
|
+
}>;
|