yet-another-react-lightbox 1.4.1 → 1.7.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/README.md +2 -0
- package/dist/Lightbox.d.ts +4 -8
- package/dist/Lightbox.js +1 -2
- package/dist/core/components/ImageSlide.d.ts +2 -1
- package/dist/core/components/ImageSlide.js +23 -11
- package/dist/core/consts.d.ts +10 -0
- package/dist/core/consts.js +9 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +1 -0
- package/dist/core/modules/Carousel.js +1 -1
- package/dist/core/modules/Controller.d.ts +7 -3
- package/dist/core/modules/Controller.js +21 -8
- package/dist/core/modules/Navigation.js +4 -4
- package/dist/plugins/Slideshow.d.ts +31 -0
- package/dist/plugins/Slideshow.js +88 -0
- package/dist/plugins/Video.d.ts +30 -4
- package/dist/plugins/Video.js +63 -17
- package/dist/plugins/index.d.ts +1 -0
- package/dist/plugins/index.js +1 -0
- package/dist/styles.css +33 -5
- package/dist/types.d.ts +13 -57
- package/dist/types.js +1 -56
- package/package.json +12 -11
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@ Modern React lightbox component. Performant, easy to use, customizable and exten
|
|
|
16
16
|
- **Video:** video slides are supported via an optional plugin
|
|
17
17
|
- **Customization:** customize any UI element or add your own custom slides
|
|
18
18
|
- **No bloat:** never bundle rarely used features; add optional features via plugins
|
|
19
|
+
- **RTL:** compatible with RTL layout
|
|
19
20
|
- **TypeScript:** type definitions come built-in in the package
|
|
20
21
|
|
|
21
22
|
## Documentation
|
|
@@ -130,6 +131,7 @@ The following plugins come bundled in the package:
|
|
|
130
131
|
description
|
|
131
132
|
- [Fullscreen](https://yet-another-react-lightbox.vercel.app/plugins/fullscreen) - adds support for fullscreen mode
|
|
132
133
|
- [Inline](https://yet-another-react-lightbox.vercel.app/plugins/inline) - adds support for inline rendering mode
|
|
134
|
+
- [Slideshow](https://yet-another-react-lightbox.vercel.app/plugins/slideshow) - adds slideshow autoplay feature
|
|
133
135
|
- [Video](https://yet-another-react-lightbox.vercel.app/plugins/video) - adds support for video slides
|
|
134
136
|
|
|
135
137
|
## License
|
package/dist/Lightbox.d.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
};
|
|
6
|
-
/** Modern React lightbox component */
|
|
7
|
-
export declare const Lightbox: (props: DeepPartial<Partial<LightboxProps>, "carousel" | "animation" | "render" | "toolbar" | "controller" | "on">) => JSX.Element;
|
|
8
|
-
export {};
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { LightboxExternalProps } from "./types.js";
|
|
3
|
+
/** Lightbox component */
|
|
4
|
+
export declare const Lightbox: React.FC<LightboxExternalProps>;
|
package/dist/Lightbox.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { LightboxDefaultProps
|
|
2
|
+
import { LightboxDefaultProps } from "./types.js";
|
|
3
3
|
import { CarouselModule, ControllerModule, CoreModule, createNode, NavigationModule, NoScrollModule, PortalModule, ToolbarModule, withPlugins, } from "./core/index.js";
|
|
4
4
|
const renderNode = (node, props) => {
|
|
5
5
|
var _a;
|
|
@@ -23,7 +23,6 @@ const LightboxComponent = (props) => {
|
|
|
23
23
|
return null;
|
|
24
24
|
return React.createElement(React.Fragment, null, renderNode(createNode(CoreModule, config), augmentedProps));
|
|
25
25
|
};
|
|
26
|
-
LightboxComponent.propTypes = LightboxPropTypes;
|
|
27
26
|
export const Lightbox = (props) => {
|
|
28
27
|
const { carousel, animation, render, toolbar, controller, on, ...restProps } = props;
|
|
29
28
|
const { carousel: defaultCarousel, animation: defaultAnimation, render: defaultRender, toolbar: defaultToolbar, controller: defaultController, on: defaultOn, ...restDefaultProps } = LightboxDefaultProps;
|
|
@@ -3,7 +3,8 @@ import { Render, SlideImage } from "../../types.js";
|
|
|
3
3
|
import { ContainerRect } from "../hooks/index.js";
|
|
4
4
|
export declare type ImageSlideProps = {
|
|
5
5
|
slide: SlideImage;
|
|
6
|
+
offset: number;
|
|
6
7
|
render?: Render;
|
|
7
8
|
rect?: ContainerRect;
|
|
8
9
|
};
|
|
9
|
-
export declare const ImageSlide: ({ slide: image, render, rect }: ImageSlideProps) => JSX.Element;
|
|
10
|
+
export declare const ImageSlide: ({ slide: image, offset, render, rect }: ImageSlideProps) => JSX.Element;
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { adjustDevicePixelRatio, clsx, cssClass, hasWindow } from "../utils.js";
|
|
3
3
|
import { useLatest } from "../hooks/index.js";
|
|
4
|
+
import { useEvents } from "../contexts/index.js";
|
|
4
5
|
import { ErrorIcon, LoadingIcon } from "./Icons.js";
|
|
5
|
-
|
|
6
|
+
import { activeSlideStatus, SLIDE_STATUS_COMPLETE, SLIDE_STATUS_ERROR, SLIDE_STATUS_LOADING } from "../consts.js";
|
|
7
|
+
import { useController } from "../modules/Controller.js";
|
|
8
|
+
export const ImageSlide = ({ slide: image, offset, render, rect }) => {
|
|
6
9
|
var _a;
|
|
7
|
-
const [
|
|
8
|
-
const
|
|
10
|
+
const [status, setStatus] = React.useState(SLIDE_STATUS_LOADING);
|
|
11
|
+
const latestStatus = useLatest(status);
|
|
12
|
+
const { latestProps } = useController();
|
|
13
|
+
const { publish } = useEvents();
|
|
9
14
|
const imageRef = React.useRef(null);
|
|
15
|
+
React.useEffect(() => {
|
|
16
|
+
if (offset === 0) {
|
|
17
|
+
publish(activeSlideStatus(status));
|
|
18
|
+
}
|
|
19
|
+
}, [offset, status, publish]);
|
|
10
20
|
const handleLoading = React.useCallback((img) => {
|
|
11
|
-
if (
|
|
21
|
+
if (latestStatus.current === SLIDE_STATUS_COMPLETE) {
|
|
12
22
|
return;
|
|
13
23
|
}
|
|
14
24
|
("decode" in img ? img.decode() : Promise.resolve())
|
|
@@ -17,9 +27,9 @@ export const ImageSlide = ({ slide: image, render, rect }) => {
|
|
|
17
27
|
if (!img.parentNode) {
|
|
18
28
|
return;
|
|
19
29
|
}
|
|
20
|
-
|
|
30
|
+
setStatus(SLIDE_STATUS_COMPLETE);
|
|
21
31
|
});
|
|
22
|
-
}, [
|
|
32
|
+
}, [latestStatus]);
|
|
23
33
|
const setImageRef = React.useCallback((img) => {
|
|
24
34
|
imageRef.current = img;
|
|
25
35
|
if (img === null || img === void 0 ? void 0 : img.complete) {
|
|
@@ -30,10 +40,12 @@ export const ImageSlide = ({ slide: image, render, rect }) => {
|
|
|
30
40
|
handleLoading(event.currentTarget);
|
|
31
41
|
}, [handleLoading]);
|
|
32
42
|
const onError = React.useCallback(() => {
|
|
33
|
-
|
|
43
|
+
setStatus(SLIDE_STATUS_ERROR);
|
|
34
44
|
}, []);
|
|
35
45
|
return (React.createElement(React.Fragment, null,
|
|
36
|
-
React.createElement("img", { ref: setImageRef, onLoad: onLoad, onError: onError, className: clsx(cssClass("slide_image"),
|
|
46
|
+
React.createElement("img", { ref: setImageRef, onLoad: onLoad, onError: onError, className: clsx(cssClass("slide_image"), (image.imageFit === "cover" ||
|
|
47
|
+
(image.imageFit !== "contain" && latestProps.current.carousel.imageFit === "cover")) &&
|
|
48
|
+
cssClass("slide_image_cover"), status !== SLIDE_STATUS_COMPLETE && cssClass("slide_image_loading")), draggable: false, alt: image.alt, ...(image.srcSet
|
|
37
49
|
? {
|
|
38
50
|
...(rect && hasWindow()
|
|
39
51
|
? {
|
|
@@ -57,9 +69,9 @@ export const ImageSlide = ({ slide: image, render, rect }) => {
|
|
|
57
69
|
}
|
|
58
70
|
: undefined,
|
|
59
71
|
}), src: image.src }),
|
|
60
|
-
|
|
61
|
-
|
|
72
|
+
status !== SLIDE_STATUS_COMPLETE && (React.createElement("div", { className: cssClass("slide_placeholder") },
|
|
73
|
+
status === SLIDE_STATUS_LOADING &&
|
|
62
74
|
((render === null || render === void 0 ? void 0 : render.iconLoading) ? (render.iconLoading()) : (React.createElement(LoadingIcon, { className: clsx(cssClass("icon"), cssClass("slide_loading")) }))),
|
|
63
|
-
|
|
75
|
+
status === SLIDE_STATUS_ERROR &&
|
|
64
76
|
((render === null || render === void 0 ? void 0 : render.iconError) ? (render.iconError()) : (React.createElement(ErrorIcon, { className: clsx(cssClass("icon"), cssClass("slide_error")) })))))));
|
|
65
77
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const SLIDE_STATUS_LOADING = "loading";
|
|
2
|
+
export declare const SLIDE_STATUS_PLAYING = "playing";
|
|
3
|
+
export declare const SLIDE_STATUS_ERROR = "error";
|
|
4
|
+
export declare const SLIDE_STATUS_COMPLETE = "complete";
|
|
5
|
+
export declare type SlideStatus = typeof SLIDE_STATUS_LOADING | typeof SLIDE_STATUS_PLAYING | typeof SLIDE_STATUS_ERROR | typeof SLIDE_STATUS_COMPLETE;
|
|
6
|
+
export declare const activeSlideStatus: (status: SlideStatus) => string;
|
|
7
|
+
export declare const ACTIVE_SLIDE_LOADING: string;
|
|
8
|
+
export declare const ACTIVE_SLIDE_PLAYING: string;
|
|
9
|
+
export declare const ACTIVE_SLIDE_ERROR: string;
|
|
10
|
+
export declare const ACTIVE_SLIDE_COMPLETE: string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const SLIDE_STATUS_LOADING = "loading";
|
|
2
|
+
export const SLIDE_STATUS_PLAYING = "playing";
|
|
3
|
+
export const SLIDE_STATUS_ERROR = "error";
|
|
4
|
+
export const SLIDE_STATUS_COMPLETE = "complete";
|
|
5
|
+
export const activeSlideStatus = (status) => `active-slide-${status}`;
|
|
6
|
+
export const ACTIVE_SLIDE_LOADING = activeSlideStatus(SLIDE_STATUS_LOADING);
|
|
7
|
+
export const ACTIVE_SLIDE_PLAYING = activeSlideStatus(SLIDE_STATUS_PLAYING);
|
|
8
|
+
export const ACTIVE_SLIDE_ERROR = activeSlideStatus(SLIDE_STATUS_ERROR);
|
|
9
|
+
export const ACTIVE_SLIDE_COMPLETE = activeSlideStatus(SLIDE_STATUS_COMPLETE);
|
package/dist/core/index.d.ts
CHANGED
package/dist/core/index.js
CHANGED
|
@@ -13,7 +13,7 @@ const CarouselSlide = ({ slide, offset }) => {
|
|
|
13
13
|
var _a, _b, _c, _d;
|
|
14
14
|
let rendered = (_a = render.slide) === null || _a === void 0 ? void 0 : _a.call(render, slide, offset, rect);
|
|
15
15
|
if (!rendered && "src" in slide) {
|
|
16
|
-
rendered = React.createElement(ImageSlide, { slide: slide, render: render, rect: rect });
|
|
16
|
+
rendered = React.createElement(ImageSlide, { slide: slide, offset: offset, render: render, rect: rect });
|
|
17
17
|
}
|
|
18
18
|
return rendered ? (React.createElement(React.Fragment, null, (_b = render.slideHeader) === null || _b === void 0 ? void 0 :
|
|
19
19
|
_b.call(render, slide),
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Component, ComponentProps } from "../../types.js";
|
|
3
3
|
import { SubscribeSensors } from "../hooks/index.js";
|
|
4
|
-
|
|
5
|
-
latestProps: React.MutableRefObject<ComponentProps>;
|
|
6
|
-
containerRef: React.RefObject<HTMLDivElement>;
|
|
4
|
+
declare type ControllerState = {
|
|
7
5
|
currentIndex: number;
|
|
8
6
|
globalIndex: number;
|
|
7
|
+
isRTL: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare type ControllerContextType = ControllerState & {
|
|
10
|
+
latestProps: React.MutableRefObject<ComponentProps>;
|
|
11
|
+
containerRef: React.RefObject<HTMLDivElement>;
|
|
9
12
|
subscribeSensors: SubscribeSensors<HTMLDivElement>;
|
|
10
13
|
};
|
|
11
14
|
export declare const useController: () => ControllerContextType;
|
|
12
15
|
export declare const Controller: Component;
|
|
13
16
|
export declare const ControllerModule: import("../../types.js").Module;
|
|
17
|
+
export {};
|
|
@@ -15,6 +15,7 @@ export const Controller = ({ children, ...props }) => {
|
|
|
15
15
|
const [state, setState] = React.useState({
|
|
16
16
|
currentIndex: props.index,
|
|
17
17
|
globalIndex: props.index,
|
|
18
|
+
isRTL: false,
|
|
18
19
|
});
|
|
19
20
|
const latestProps = useLatest(props);
|
|
20
21
|
const refs = React.useRef({
|
|
@@ -29,7 +30,11 @@ export const Controller = ({ children, ...props }) => {
|
|
|
29
30
|
refs.current.state = state;
|
|
30
31
|
refs.current.props = props;
|
|
31
32
|
useEnhancedEffect(() => {
|
|
32
|
-
const preventDefault = (event) =>
|
|
33
|
+
const preventDefault = (event) => {
|
|
34
|
+
if (Math.abs(event.deltaX) > Math.abs(event.deltaY)) {
|
|
35
|
+
event.preventDefault();
|
|
36
|
+
}
|
|
37
|
+
};
|
|
33
38
|
const node = containerRef.current;
|
|
34
39
|
if (node) {
|
|
35
40
|
node.addEventListener("wheel", preventDefault, { passive: false });
|
|
@@ -40,6 +45,12 @@ export const Controller = ({ children, ...props }) => {
|
|
|
40
45
|
}
|
|
41
46
|
};
|
|
42
47
|
}, [containerRef]);
|
|
48
|
+
useEnhancedEffect(() => {
|
|
49
|
+
const node = containerRef.current;
|
|
50
|
+
if (node) {
|
|
51
|
+
setState((prev) => ({ ...prev, isRTL: window.getComputedStyle(node).direction === "rtl" }));
|
|
52
|
+
}
|
|
53
|
+
}, [containerRef]);
|
|
43
54
|
React.useEffect(() => {
|
|
44
55
|
var _a;
|
|
45
56
|
if (refs.current.props.controller.focus) {
|
|
@@ -76,11 +87,12 @@ export const Controller = ({ children, ...props }) => {
|
|
|
76
87
|
clearTimeout(current.swipeIntentCleanup);
|
|
77
88
|
current.swipeIntentCleanup = undefined;
|
|
78
89
|
}, [clearTimeout]);
|
|
90
|
+
const rtl = React.useCallback((value) => (refs.current.state.isRTL ? -1 : 1) * (typeof value === "number" ? value : 1), [refs]);
|
|
79
91
|
const isSwipeValid = React.useCallback((offset) => {
|
|
80
92
|
const { state: { currentIndex }, props: { carousel, slides }, } = refs.current;
|
|
81
93
|
return !(carousel.finite &&
|
|
82
|
-
((offset > 0 && currentIndex === 0) || (offset < 0 && currentIndex === slides.length - 1)));
|
|
83
|
-
}, []);
|
|
94
|
+
((rtl(offset) > 0 && currentIndex === 0) || (rtl(offset) < 0 && currentIndex === slides.length - 1)));
|
|
95
|
+
}, [rtl]);
|
|
84
96
|
const swipe = React.useCallback((direction) => {
|
|
85
97
|
var _a;
|
|
86
98
|
const { current } = refs;
|
|
@@ -105,7 +117,7 @@ export const Controller = ({ children, ...props }) => {
|
|
|
105
117
|
newSwipeAnimationDuration =
|
|
106
118
|
(newSwipeAnimationDuration / expectedTime) * Math.max(elapsedTime, expectedTime / 5);
|
|
107
119
|
}
|
|
108
|
-
direction = swipeOffset > 0 ? "prev" : "next";
|
|
120
|
+
direction = rtl(swipeOffset) > 0 ? "prev" : "next";
|
|
109
121
|
}
|
|
110
122
|
else {
|
|
111
123
|
newSwipeAnimationDuration = swipeAnimationDuration / 2;
|
|
@@ -113,7 +125,7 @@ export const Controller = ({ children, ...props }) => {
|
|
|
113
125
|
}
|
|
114
126
|
const newState = {};
|
|
115
127
|
if (direction === "prev") {
|
|
116
|
-
if (isSwipeValid(1)) {
|
|
128
|
+
if (isSwipeValid(rtl(1))) {
|
|
117
129
|
newState.currentIndex = (currentIndex - 1 + slidesCount) % slidesCount;
|
|
118
130
|
newState.globalIndex = globalIndex - 1;
|
|
119
131
|
}
|
|
@@ -123,7 +135,7 @@ export const Controller = ({ children, ...props }) => {
|
|
|
123
135
|
}
|
|
124
136
|
}
|
|
125
137
|
else if (direction === "next") {
|
|
126
|
-
if (isSwipeValid(-1)) {
|
|
138
|
+
if (isSwipeValid(rtl(-1))) {
|
|
127
139
|
newState.currentIndex = (currentIndex + 1) % slidesCount;
|
|
128
140
|
newState.globalIndex = globalIndex + 1;
|
|
129
141
|
}
|
|
@@ -143,7 +155,7 @@ export const Controller = ({ children, ...props }) => {
|
|
|
143
155
|
}, newSwipeAnimationDuration);
|
|
144
156
|
}
|
|
145
157
|
setState((prev) => ({ ...prev, ...newState }));
|
|
146
|
-
}, [setTimeout, resetSwipe, isSwipeValid, rerender, containerRef]);
|
|
158
|
+
}, [setTimeout, resetSwipe, isSwipeValid, rerender, containerRef, rtl]);
|
|
147
159
|
React.useEffect(() => cleanup(subscribe("prev", () => swipe("prev")), subscribe("next", () => swipe("next"))), [subscribe, swipe]);
|
|
148
160
|
React.useEffect(() => subscribeSensors("onKeyUp", (event) => {
|
|
149
161
|
if (event.code === "Escape") {
|
|
@@ -266,8 +278,9 @@ export const Controller = ({ children, ...props }) => {
|
|
|
266
278
|
containerRef,
|
|
267
279
|
currentIndex: state.currentIndex,
|
|
268
280
|
globalIndex: state.globalIndex,
|
|
281
|
+
isRTL: state.isRTL,
|
|
269
282
|
subscribeSensors,
|
|
270
|
-
}), [latestProps, containerRef, state.currentIndex, state.globalIndex, subscribeSensors]);
|
|
283
|
+
}), [latestProps, containerRef, state.currentIndex, state.globalIndex, state.isRTL, subscribeSensors]);
|
|
271
284
|
return (React.createElement("div", { ref: setContainerRef, className: clsx(cssClass("container"), refs.current.swipeState === "swipe" && cssClass("container_swipe")), style: refs.current.swipeAnimationDuration !== LightboxDefaultProps.animation.swipe
|
|
272
285
|
? {
|
|
273
286
|
[cssVar("swipe_animation_duration")]: `${Math.round(refs.current.swipeAnimationDuration)}ms`,
|
|
@@ -8,16 +8,16 @@ export const NavigationButton = ({ publish, labels, label, icon, renderIcon, act
|
|
|
8
8
|
publish(action);
|
|
9
9
|
} }));
|
|
10
10
|
export const Navigation = ({ slides, carousel: { finite }, labels, render: { buttonPrev, buttonNext, iconPrev, iconNext }, }) => {
|
|
11
|
-
const { currentIndex, subscribeSensors } = useController();
|
|
11
|
+
const { currentIndex, subscribeSensors, isRTL } = useController();
|
|
12
12
|
const { publish } = useEvents();
|
|
13
13
|
React.useEffect(() => subscribeSensors("onKeyUp", (event) => {
|
|
14
14
|
if (event.code === "ArrowLeft") {
|
|
15
|
-
publish("prev");
|
|
15
|
+
publish(isRTL ? "next" : "prev");
|
|
16
16
|
}
|
|
17
17
|
else if (event.code === "ArrowRight") {
|
|
18
|
-
publish("next");
|
|
18
|
+
publish(isRTL ? "prev" : "next");
|
|
19
19
|
}
|
|
20
|
-
}), [subscribeSensors, publish]);
|
|
20
|
+
}), [subscribeSensors, publish, isRTL]);
|
|
21
21
|
return (React.createElement(React.Fragment, null,
|
|
22
22
|
buttonPrev ? (buttonPrev()) : (React.createElement(NavigationButton, { label: "Previous", action: "prev", icon: PreviousIcon, renderIcon: iconPrev, disabled: finite && currentIndex === 0, labels: labels, publish: publish })),
|
|
23
23
|
buttonNext ? (buttonNext()) : (React.createElement(NavigationButton, { label: "Next", action: "next", icon: NextIcon, renderIcon: iconNext, disabled: finite && currentIndex === slides.length - 1, labels: labels, publish: publish }))));
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Plugin } from "../types.js";
|
|
3
|
+
declare module "../types.js" {
|
|
4
|
+
interface LightboxProps {
|
|
5
|
+
/** Slideshow plugin settings */
|
|
6
|
+
slideshow?: {
|
|
7
|
+
/** if `true`, slideshow is turned on automatically when the lightbox opens */
|
|
8
|
+
autoplay?: boolean;
|
|
9
|
+
/** slideshow delay in milliseconds */
|
|
10
|
+
delay?: number;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
interface Render {
|
|
14
|
+
/** render custom Slideshow Play icon */
|
|
15
|
+
iconSlideshowPlay?: () => React.ReactNode;
|
|
16
|
+
/** render custom Slideshow Pause icon */
|
|
17
|
+
iconSlideshowPause?: () => React.ReactNode;
|
|
18
|
+
/** render custom Slideshow button */
|
|
19
|
+
buttonSlideshow?: ({ playing, togglePlaying, disabled, }: {
|
|
20
|
+
/** current slideshow autoplay status */
|
|
21
|
+
playing: boolean;
|
|
22
|
+
/** toggle slideshow autoplay status */
|
|
23
|
+
togglePlaying: () => void;
|
|
24
|
+
/** if `true`, the button is disabled */
|
|
25
|
+
disabled: boolean;
|
|
26
|
+
}) => React.ReactNode;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** Slideshow plugin */
|
|
30
|
+
export declare const Slideshow: Plugin;
|
|
31
|
+
export default Slideshow;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { ACTIVE_SLIDE_COMPLETE, ACTIVE_SLIDE_ERROR, ACTIVE_SLIDE_LOADING, ACTIVE_SLIDE_PLAYING, cleanup, createIcon, IconButton, label, SLIDE_STATUS_COMPLETE, SLIDE_STATUS_ERROR, SLIDE_STATUS_LOADING, SLIDE_STATUS_PLAYING, useController, useEvents, useLatest, useTimeouts, } from "../core/index.js";
|
|
3
|
+
const defaultSlideshowProps = {
|
|
4
|
+
autoplay: false,
|
|
5
|
+
delay: 3000,
|
|
6
|
+
};
|
|
7
|
+
const PlayIcon = createIcon("Play", React.createElement("path", { d: "M8 5v14l11-7z" }));
|
|
8
|
+
const PauseIcon = createIcon("Pause", React.createElement("path", { d: "M6 19h4V5H6v14zm8-14v14h4V5h-4z" }));
|
|
9
|
+
const SlideshowButton = () => {
|
|
10
|
+
const { currentIndex, latestProps } = useController();
|
|
11
|
+
const { setTimeout, clearTimeout } = useTimeouts();
|
|
12
|
+
const { publish, subscribe } = useEvents();
|
|
13
|
+
const slideshow = {
|
|
14
|
+
...defaultSlideshowProps,
|
|
15
|
+
...latestProps.current.slideshow,
|
|
16
|
+
};
|
|
17
|
+
const [playing, setPlaying] = React.useState(slideshow.autoplay);
|
|
18
|
+
const scheduler = React.useRef();
|
|
19
|
+
const refs = useLatest({
|
|
20
|
+
playing,
|
|
21
|
+
delay: slideshow.delay,
|
|
22
|
+
currentIndex,
|
|
23
|
+
finite: latestProps.current.carousel.finite,
|
|
24
|
+
slidesCount: latestProps.current.slides.length,
|
|
25
|
+
});
|
|
26
|
+
const slideStatus = React.useRef();
|
|
27
|
+
const cancelScheduler = React.useCallback(() => {
|
|
28
|
+
clearTimeout(scheduler.current);
|
|
29
|
+
scheduler.current = undefined;
|
|
30
|
+
}, [clearTimeout]);
|
|
31
|
+
const reachedLastSlide = React.useCallback(() => refs.current.finite && refs.current.currentIndex === refs.current.slidesCount - 1, [refs]);
|
|
32
|
+
const scheduleNextSlide = React.useCallback(() => {
|
|
33
|
+
cancelScheduler();
|
|
34
|
+
if (!refs.current.playing ||
|
|
35
|
+
reachedLastSlide() ||
|
|
36
|
+
slideStatus.current === SLIDE_STATUS_LOADING ||
|
|
37
|
+
slideStatus.current === SLIDE_STATUS_PLAYING) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
scheduler.current = setTimeout(() => {
|
|
41
|
+
if (refs.current.playing) {
|
|
42
|
+
slideStatus.current = undefined;
|
|
43
|
+
publish("next");
|
|
44
|
+
}
|
|
45
|
+
}, refs.current.delay);
|
|
46
|
+
}, [publish, setTimeout, cancelScheduler, refs, reachedLastSlide]);
|
|
47
|
+
const togglePlaying = React.useCallback(() => {
|
|
48
|
+
setPlaying((prev) => !prev);
|
|
49
|
+
}, []);
|
|
50
|
+
React.useEffect(() => {
|
|
51
|
+
scheduleNextSlide();
|
|
52
|
+
}, [currentIndex, playing, scheduleNextSlide]);
|
|
53
|
+
React.useEffect(() => {
|
|
54
|
+
if (playing && reachedLastSlide()) {
|
|
55
|
+
setPlaying(false);
|
|
56
|
+
}
|
|
57
|
+
}, [currentIndex, playing, reachedLastSlide]);
|
|
58
|
+
React.useEffect(() => cleanup(subscribe(ACTIVE_SLIDE_LOADING, () => {
|
|
59
|
+
slideStatus.current = SLIDE_STATUS_LOADING;
|
|
60
|
+
cancelScheduler();
|
|
61
|
+
}), subscribe(ACTIVE_SLIDE_PLAYING, () => {
|
|
62
|
+
slideStatus.current = SLIDE_STATUS_PLAYING;
|
|
63
|
+
cancelScheduler();
|
|
64
|
+
}), subscribe(ACTIVE_SLIDE_ERROR, () => {
|
|
65
|
+
slideStatus.current = SLIDE_STATUS_ERROR;
|
|
66
|
+
scheduleNextSlide();
|
|
67
|
+
}), subscribe(ACTIVE_SLIDE_COMPLETE, () => {
|
|
68
|
+
slideStatus.current = SLIDE_STATUS_COMPLETE;
|
|
69
|
+
scheduleNextSlide();
|
|
70
|
+
})), [subscribe, cancelScheduler, scheduleNextSlide]);
|
|
71
|
+
const { render, labels } = latestProps.current;
|
|
72
|
+
const disabled = reachedLastSlide();
|
|
73
|
+
return render.buttonSlideshow ? (React.createElement(React.Fragment, null, render.buttonSlideshow({ playing, togglePlaying, disabled }))) : (React.createElement(IconButton, { label: playing ? label(labels, "Pause") : label(labels, "Play"), icon: playing ? PauseIcon : PlayIcon, renderIcon: playing ? render.iconSlideshowPause : render.iconSlideshowPlay, onClick: togglePlaying, disabled: disabled, "aria-disabled": disabled }));
|
|
74
|
+
};
|
|
75
|
+
export const Slideshow = ({ augment }) => {
|
|
76
|
+
augment(({ slideshow: originalSlideshow, toolbar: { buttons, ...restToolbar }, ...restProps }) => ({
|
|
77
|
+
toolbar: {
|
|
78
|
+
buttons: [React.createElement(SlideshowButton, { key: "slideshow" }), ...buttons],
|
|
79
|
+
...restToolbar,
|
|
80
|
+
},
|
|
81
|
+
slideshow: {
|
|
82
|
+
...defaultSlideshowProps,
|
|
83
|
+
...originalSlideshow,
|
|
84
|
+
},
|
|
85
|
+
...restProps,
|
|
86
|
+
}));
|
|
87
|
+
};
|
|
88
|
+
export default Slideshow;
|
package/dist/plugins/Video.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import * as React from "react";
|
|
2
2
|
import { Plugin } from "../types.js";
|
|
3
3
|
/** Video slide attributes */
|
|
4
4
|
export interface SlideVideo {
|
|
@@ -10,6 +10,26 @@ export interface SlideVideo {
|
|
|
10
10
|
width?: number;
|
|
11
11
|
/** video height in pixels */
|
|
12
12
|
height?: number;
|
|
13
|
+
/** if `true`, the video automatically begins to play */
|
|
14
|
+
autoPlay?: boolean;
|
|
15
|
+
/** if `true`, the browser will offer controls to allow the user to control video playback */
|
|
16
|
+
controls?: boolean;
|
|
17
|
+
/** indicates what controls to show */
|
|
18
|
+
controlsList?: string;
|
|
19
|
+
/** indicates whether to use CORS to fetch the related video */
|
|
20
|
+
crossOrigin?: string;
|
|
21
|
+
/** video preload setting */
|
|
22
|
+
preload?: string;
|
|
23
|
+
/** if `true`, the browser will automatically seek back to the start upon reaching the end of the video */
|
|
24
|
+
loop?: boolean;
|
|
25
|
+
/** the default setting of the audio contained in the video */
|
|
26
|
+
muted?: boolean;
|
|
27
|
+
/** if `true`, the video is to be played "inline", that is within the element's playback area */
|
|
28
|
+
playsInline?: boolean;
|
|
29
|
+
/** prevents the browser from suggesting a Picture-in-Picture context menu */
|
|
30
|
+
disablePictureInPicture?: boolean;
|
|
31
|
+
/** disables the capability of remote playback */
|
|
32
|
+
disableRemotePlayback?: boolean;
|
|
13
33
|
/** an array of video files */
|
|
14
34
|
sources?: {
|
|
15
35
|
/** video source URL */
|
|
@@ -23,11 +43,17 @@ declare module "../types.js" {
|
|
|
23
43
|
/** video slide type */
|
|
24
44
|
SlideVideo: SlideVideo;
|
|
25
45
|
}
|
|
46
|
+
interface LightboxProps {
|
|
47
|
+
/** video plugin settings */
|
|
48
|
+
video?: Pick<SlideVideo, "autoPlay" | "controls" | "controlsList" | "crossOrigin" | "preload" | "loop" | "muted" | "playsInline" | "disablePictureInPicture" | "disableRemotePlayback">;
|
|
49
|
+
}
|
|
26
50
|
}
|
|
27
|
-
|
|
28
|
-
export declare const VideoSlide: ({ slide: { sources, poster, width, height } }: {
|
|
51
|
+
declare type VideoSlideProps = {
|
|
29
52
|
slide: SlideVideo;
|
|
30
|
-
|
|
53
|
+
offset: number;
|
|
54
|
+
};
|
|
55
|
+
/** Video slide */
|
|
56
|
+
export declare const VideoSlide: React.FC<VideoSlideProps>;
|
|
31
57
|
/** Video plugin */
|
|
32
58
|
export declare const Video: Plugin;
|
|
33
59
|
export default Video;
|
package/dist/plugins/Video.js
CHANGED
|
@@ -1,19 +1,40 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
src: PropTypes.string.isRequired,
|
|
12
|
-
type: PropTypes.string.isRequired,
|
|
13
|
-
}).isRequired),
|
|
14
|
-
}));
|
|
15
|
-
export const VideoSlide = ({ slide: { sources, poster, width, height } }) => {
|
|
2
|
+
import { ACTIVE_SLIDE_COMPLETE, ACTIVE_SLIDE_LOADING, ACTIVE_SLIDE_PLAYING, clsx, cssClass, useContainerRect, useController, useEvents, useLatest, } from "../core/index.js";
|
|
3
|
+
const defaultVideoProps = {
|
|
4
|
+
controls: true,
|
|
5
|
+
playsInline: true,
|
|
6
|
+
};
|
|
7
|
+
export const VideoSlide = ({ slide, offset }) => {
|
|
8
|
+
var _a;
|
|
9
|
+
const { latestProps } = useController();
|
|
10
|
+
const { publish } = useEvents();
|
|
16
11
|
const { setContainerRef, containerRect } = useContainerRect();
|
|
12
|
+
const videoRef = React.useRef(null);
|
|
13
|
+
const video = (_a = latestProps.current.video) !== null && _a !== void 0 ? _a : defaultVideoProps;
|
|
14
|
+
React.useEffect(() => {
|
|
15
|
+
if (offset !== 0 && videoRef.current && !videoRef.current.paused) {
|
|
16
|
+
videoRef.current.pause();
|
|
17
|
+
}
|
|
18
|
+
}, [offset]);
|
|
19
|
+
React.useEffect(() => {
|
|
20
|
+
if (offset === 0 && videoRef.current && (slide.autoPlay || video.autoPlay)) {
|
|
21
|
+
publish(ACTIVE_SLIDE_LOADING);
|
|
22
|
+
videoRef.current.play().catch(() => { });
|
|
23
|
+
}
|
|
24
|
+
}, [offset, video.autoPlay, slide.autoPlay, publish]);
|
|
25
|
+
const latestOffset = useLatest(offset);
|
|
26
|
+
const latestVideoAutoPlay = useLatest(video.autoPlay);
|
|
27
|
+
const latestSlideAutoPlay = useLatest(slide.autoPlay);
|
|
28
|
+
const setVideoRef = React.useCallback((el) => {
|
|
29
|
+
videoRef.current = el;
|
|
30
|
+
if (el &&
|
|
31
|
+
latestOffset.current === 0 &&
|
|
32
|
+
(latestVideoAutoPlay.current || latestSlideAutoPlay.current) &&
|
|
33
|
+
el.paused) {
|
|
34
|
+
el.play().catch(() => { });
|
|
35
|
+
}
|
|
36
|
+
}, [latestOffset, latestVideoAutoPlay, latestSlideAutoPlay]);
|
|
37
|
+
const { width, height, poster, sources } = slide;
|
|
17
38
|
const scaleWidthAndHeight = () => {
|
|
18
39
|
if (!width || !height || !containerRect)
|
|
19
40
|
return null;
|
|
@@ -23,23 +44,48 @@ export const VideoSlide = ({ slide: { sources, poster, width, height } }) => {
|
|
|
23
44
|
height: !widthBound ? containerRect.height : Math.round((containerRect.width / width) * height),
|
|
24
45
|
};
|
|
25
46
|
};
|
|
47
|
+
const resolveBoolean = (attr) => {
|
|
48
|
+
if (slide[attr] === false)
|
|
49
|
+
return null;
|
|
50
|
+
if (slide[attr] === true)
|
|
51
|
+
return { [attr]: true };
|
|
52
|
+
if (video[attr] === false)
|
|
53
|
+
return null;
|
|
54
|
+
if (video[attr] === true)
|
|
55
|
+
return { [attr]: true };
|
|
56
|
+
return null;
|
|
57
|
+
};
|
|
58
|
+
const resolveString = (attr) => {
|
|
59
|
+
if (video[attr] || slide[attr]) {
|
|
60
|
+
return { [attr]: slide[attr] || video[attr] };
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
};
|
|
26
64
|
return (React.createElement(React.Fragment, null, sources && (React.createElement("div", { ref: setContainerRef, style: {
|
|
27
65
|
width: "100%",
|
|
28
66
|
height: "100%",
|
|
29
67
|
...(width ? { maxWidth: `${width}px` } : null),
|
|
30
|
-
}, className: clsx(cssClass("video_container"), cssClass("flex_center")) }, containerRect && (React.createElement("video", {
|
|
68
|
+
}, className: clsx(cssClass("video_container"), cssClass("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: () => {
|
|
69
|
+
publish(ACTIVE_SLIDE_PLAYING);
|
|
70
|
+
}, onEnded: () => {
|
|
71
|
+
publish(ACTIVE_SLIDE_COMPLETE);
|
|
72
|
+
} }, sources.map(({ src, type }, index) => (React.createElement("source", { key: index, src: src, type: type })))))))));
|
|
31
73
|
};
|
|
32
74
|
export const Video = ({ augment }) => {
|
|
33
|
-
augment(({ render: { slide: renderSlide, ...restRender }, ...restProps }) => ({
|
|
75
|
+
augment(({ render: { slide: renderSlide, ...restRender }, video: originalVideo, ...restProps }) => ({
|
|
34
76
|
render: {
|
|
35
77
|
slide: (slide, offset, rect) => {
|
|
36
78
|
if ("type" in slide && slide.type === "video") {
|
|
37
|
-
return React.createElement(VideoSlide, { slide: slide });
|
|
79
|
+
return React.createElement(VideoSlide, { slide: slide, offset: offset });
|
|
38
80
|
}
|
|
39
81
|
return renderSlide === null || renderSlide === void 0 ? void 0 : renderSlide(slide, offset, rect);
|
|
40
82
|
},
|
|
41
83
|
...restRender,
|
|
42
84
|
},
|
|
85
|
+
video: {
|
|
86
|
+
...defaultVideoProps,
|
|
87
|
+
...originalVideo,
|
|
88
|
+
},
|
|
43
89
|
...restProps,
|
|
44
90
|
}));
|
|
45
91
|
};
|
package/dist/plugins/index.d.ts
CHANGED
package/dist/plugins/index.js
CHANGED
package/dist/styles.css
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
-moz-user-select: none;
|
|
15
15
|
-ms-user-select: none;
|
|
16
16
|
user-select: none;
|
|
17
|
-
touch-action:
|
|
17
|
+
touch-action: pan-y;
|
|
18
18
|
}
|
|
19
19
|
.yarl__container {
|
|
20
20
|
width: 100%;
|
|
@@ -41,15 +41,18 @@
|
|
|
41
41
|
overflow: hidden;
|
|
42
42
|
inset: 0;
|
|
43
43
|
padding: var(--yarl__carousel_padding, 16px);
|
|
44
|
-
-webkit-transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%))), 0, 0);
|
|
45
|
-
transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%))), 0, 0);
|
|
44
|
+
-webkit-transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%)) * var(--yarl__direction, 1)), 0, 0);
|
|
45
|
+
transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%)) * var(--yarl__direction, 1)), 0, 0);
|
|
46
46
|
transition: -webkit-transform var(--yarl__swipe_animation_duration, 500ms) ease-out;
|
|
47
47
|
transition: transform var(--yarl__swipe_animation_duration, 500ms) ease-out;
|
|
48
48
|
transition: transform var(--yarl__swipe_animation_duration, 500ms) ease-out, -webkit-transform var(--yarl__swipe_animation_duration, 500ms) ease-out;
|
|
49
49
|
}
|
|
50
|
+
[dir=rtl] .yarl__slide {
|
|
51
|
+
--yarl__direction: -1;
|
|
52
|
+
}
|
|
50
53
|
.yarl__container_swipe .yarl__slide {
|
|
51
|
-
-webkit-transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%))), 0, 0) translate3d(var(--yarl__swipe_offset, 0px), 0, 0);
|
|
52
|
-
transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%))), 0, 0) translate3d(var(--yarl__swipe_offset, 0px), 0, 0);
|
|
54
|
+
-webkit-transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%)) * var(--yarl__direction, 1)), 0, 0) translate3d(var(--yarl__swipe_offset, 0px), 0, 0);
|
|
55
|
+
transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%)) * var(--yarl__direction, 1)), 0, 0) translate3d(var(--yarl__swipe_offset, 0px), 0, 0);
|
|
53
56
|
transition: unset;
|
|
54
57
|
}
|
|
55
58
|
.yarl__slide_image {
|
|
@@ -62,6 +65,12 @@
|
|
|
62
65
|
user-select: none;
|
|
63
66
|
-webkit-user-select: none;
|
|
64
67
|
-webkit-touch-callout: none;
|
|
68
|
+
-webkit-transform: translate3d(0, 0, 0);
|
|
69
|
+
transform: translate3d(0, 0, 0);
|
|
70
|
+
}
|
|
71
|
+
.yarl__slide_image_cover {
|
|
72
|
+
-o-object-fit: cover;
|
|
73
|
+
object-fit: cover;
|
|
65
74
|
}
|
|
66
75
|
.yarl__slide_image_loading {
|
|
67
76
|
opacity: 0;
|
|
@@ -137,6 +146,9 @@
|
|
|
137
146
|
padding: 8px;
|
|
138
147
|
gap: 8px;
|
|
139
148
|
}
|
|
149
|
+
[dir=rtl] .yarl__toolbar {
|
|
150
|
+
inset: 0 auto auto 0;
|
|
151
|
+
}
|
|
140
152
|
.yarl__icon {
|
|
141
153
|
width: 32px;
|
|
142
154
|
height: 32px;
|
|
@@ -185,9 +197,21 @@
|
|
|
185
197
|
.yarl__navigation_prev {
|
|
186
198
|
left: 0;
|
|
187
199
|
}
|
|
200
|
+
[dir=rtl] .yarl__navigation_prev {
|
|
201
|
+
left: unset;
|
|
202
|
+
right: 0;
|
|
203
|
+
-webkit-transform: translateY(-50%) rotate(180deg);
|
|
204
|
+
transform: translateY(-50%) rotate(180deg);
|
|
205
|
+
}
|
|
188
206
|
.yarl__navigation_next {
|
|
189
207
|
right: 0;
|
|
190
208
|
}
|
|
209
|
+
[dir=rtl] .yarl__navigation_next {
|
|
210
|
+
left: 0;
|
|
211
|
+
right: unset;
|
|
212
|
+
-webkit-transform: translateY(-50%) rotate(180deg);
|
|
213
|
+
transform: translateY(-50%) rotate(180deg);
|
|
214
|
+
}
|
|
191
215
|
.yarl__no_scroll {
|
|
192
216
|
height: 100%;
|
|
193
217
|
overflow: hidden;
|
|
@@ -195,6 +219,10 @@
|
|
|
195
219
|
.yarl__pad_scrollbar {
|
|
196
220
|
padding-right: var(--yarl__scrollbar_padding, 17px);
|
|
197
221
|
}
|
|
222
|
+
[dir=rtl] .yarl__pad_scrollbar {
|
|
223
|
+
padding-right: unset;
|
|
224
|
+
padding-left: var(--yarl__scrollbar_padding, 17px);
|
|
225
|
+
}
|
|
198
226
|
|
|
199
227
|
@-webkit-keyframes yarl__delayed_fadein {
|
|
200
228
|
0% {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import PropTypes from "prop-types";
|
|
3
2
|
import { ContainerRect } from "./core/hooks/useContainerRect.js";
|
|
3
|
+
/** Image fit setting */
|
|
4
|
+
export declare type ImageFit = "contain" | "cover";
|
|
4
5
|
/** Image slide properties */
|
|
5
6
|
export interface SlideImage {
|
|
6
7
|
/** image URL */
|
|
@@ -9,6 +10,8 @@ export interface SlideImage {
|
|
|
9
10
|
alt?: string;
|
|
10
11
|
/** image aspect ratio */
|
|
11
12
|
aspectRatio?: number;
|
|
13
|
+
/** `object-fit` setting */
|
|
14
|
+
imageFit?: ImageFit;
|
|
12
15
|
/** alternative images to be passed to the 'srcSet' */
|
|
13
16
|
srcSet?: {
|
|
14
17
|
/** image URL */
|
|
@@ -34,6 +37,8 @@ export interface CarouselSettings {
|
|
|
34
37
|
padding: string | number;
|
|
35
38
|
/** spacing between slides (e.g., "100px", "50%" or 0) */
|
|
36
39
|
spacing: string | number;
|
|
40
|
+
/** `object-fit` setting for image slides */
|
|
41
|
+
imageFit: ImageFit;
|
|
37
42
|
}
|
|
38
43
|
/** Animation settings */
|
|
39
44
|
export interface AnimationSettings {
|
|
@@ -44,7 +49,7 @@ export interface AnimationSettings {
|
|
|
44
49
|
}
|
|
45
50
|
/** Controller settings */
|
|
46
51
|
export interface ControllerSettings {
|
|
47
|
-
/** if true, the lightbox captures focus when it opens
|
|
52
|
+
/** if true, the lightbox captures focus when it opens */
|
|
48
53
|
focus: boolean;
|
|
49
54
|
}
|
|
50
55
|
/** Custom render functions. */
|
|
@@ -123,61 +128,6 @@ export interface LightboxProps {
|
|
|
123
128
|
/** lifecycle callbacks */
|
|
124
129
|
on: Callbacks;
|
|
125
130
|
}
|
|
126
|
-
export declare const ImageSlidePropTypes: PropTypes.Requireable<PropTypes.InferProps<{
|
|
127
|
-
src: PropTypes.Requireable<string>;
|
|
128
|
-
alt: PropTypes.Requireable<string>;
|
|
129
|
-
aspectRatio: PropTypes.Requireable<number>;
|
|
130
|
-
srcSet: PropTypes.Requireable<PropTypes.InferProps<{
|
|
131
|
-
src: PropTypes.Validator<string>;
|
|
132
|
-
width: PropTypes.Validator<number>;
|
|
133
|
-
}>[]>;
|
|
134
|
-
}>>;
|
|
135
|
-
export declare const SlideTypesPropTypes: PropTypes.Validator<any>[];
|
|
136
|
-
export declare const LightboxPropTypes: {
|
|
137
|
-
open: PropTypes.Validator<boolean>;
|
|
138
|
-
close: PropTypes.Validator<(...args: any[]) => any>;
|
|
139
|
-
index: PropTypes.Validator<number>;
|
|
140
|
-
slides: PropTypes.Validator<any[]>;
|
|
141
|
-
render: PropTypes.Validator<PropTypes.InferProps<{
|
|
142
|
-
slide: PropTypes.Requireable<(...args: any[]) => any>;
|
|
143
|
-
slideHeader: PropTypes.Requireable<(...args: any[]) => any>;
|
|
144
|
-
slideFooter: PropTypes.Requireable<(...args: any[]) => any>;
|
|
145
|
-
slideContainer: PropTypes.Requireable<(...args: any[]) => any>;
|
|
146
|
-
iconPrev: PropTypes.Requireable<(...args: any[]) => any>;
|
|
147
|
-
iconNext: PropTypes.Requireable<(...args: any[]) => any>;
|
|
148
|
-
iconClose: PropTypes.Requireable<(...args: any[]) => any>;
|
|
149
|
-
iconLoading: PropTypes.Requireable<(...args: any[]) => any>;
|
|
150
|
-
iconError: PropTypes.Requireable<(...args: any[]) => any>;
|
|
151
|
-
buttonPrev: PropTypes.Requireable<(...args: any[]) => any>;
|
|
152
|
-
buttonNext: PropTypes.Requireable<(...args: any[]) => any>;
|
|
153
|
-
buttonClose: PropTypes.Requireable<(...args: any[]) => any>;
|
|
154
|
-
}>>;
|
|
155
|
-
plugins: PropTypes.Validator<((...args: any[]) => any)[]>;
|
|
156
|
-
toolbar: PropTypes.Validator<PropTypes.InferProps<{
|
|
157
|
-
buttons: PropTypes.Validator<(string | number | boolean | PropTypes.ReactElementLike | PropTypes.ReactNodeArray | null | undefined)[]>;
|
|
158
|
-
}>>;
|
|
159
|
-
labels: PropTypes.Validator<PropTypes.InferProps<{}>>;
|
|
160
|
-
carousel: PropTypes.Validator<PropTypes.InferProps<{
|
|
161
|
-
finite: PropTypes.Validator<boolean>;
|
|
162
|
-
preload: PropTypes.Validator<number>;
|
|
163
|
-
padding: PropTypes.Validator<string | number>;
|
|
164
|
-
spacing: PropTypes.Validator<string | number>;
|
|
165
|
-
}>>;
|
|
166
|
-
animation: PropTypes.Validator<PropTypes.InferProps<{
|
|
167
|
-
fade: PropTypes.Validator<number>;
|
|
168
|
-
swipe: PropTypes.Validator<number>;
|
|
169
|
-
}>>;
|
|
170
|
-
controller: PropTypes.Validator<PropTypes.InferProps<{
|
|
171
|
-
focus: PropTypes.Validator<boolean>;
|
|
172
|
-
}>>;
|
|
173
|
-
on: PropTypes.Validator<PropTypes.InferProps<{
|
|
174
|
-
view: PropTypes.Requireable<(...args: any[]) => any>;
|
|
175
|
-
entering: PropTypes.Requireable<(...args: any[]) => any>;
|
|
176
|
-
entered: PropTypes.Requireable<(...args: any[]) => any>;
|
|
177
|
-
exiting: PropTypes.Requireable<(...args: any[]) => any>;
|
|
178
|
-
exited: PropTypes.Requireable<(...args: any[]) => any>;
|
|
179
|
-
}>>;
|
|
180
|
-
};
|
|
181
131
|
export declare const LightboxDefaultProps: {
|
|
182
132
|
open: boolean;
|
|
183
133
|
close: () => void;
|
|
@@ -238,3 +188,9 @@ export declare type PluginMethods = {
|
|
|
238
188
|
};
|
|
239
189
|
/** Lightbox plugin */
|
|
240
190
|
export declare type Plugin = ({ addParent, addChild, addSibling, replace, remove, augment }: PluginMethods) => void;
|
|
191
|
+
/** Deep partial utility type */
|
|
192
|
+
export declare type DeepPartial<T, K extends keyof T> = Omit<T, K> & {
|
|
193
|
+
[P in keyof Pick<T, K>]?: Partial<Pick<T, K>[P]>;
|
|
194
|
+
};
|
|
195
|
+
/** Lightbox external props */
|
|
196
|
+
export declare type LightboxExternalProps = DeepPartial<Partial<LightboxProps>, "carousel" | "animation" | "render" | "toolbar" | "controller" | "on">;
|
package/dist/types.js
CHANGED
|
@@ -1,59 +1,3 @@
|
|
|
1
|
-
import PropTypes from "prop-types";
|
|
2
|
-
export const ImageSlidePropTypes = PropTypes.shape({
|
|
3
|
-
src: PropTypes.string,
|
|
4
|
-
alt: PropTypes.string,
|
|
5
|
-
aspectRatio: PropTypes.number,
|
|
6
|
-
srcSet: PropTypes.arrayOf(PropTypes.shape({
|
|
7
|
-
src: PropTypes.string.isRequired,
|
|
8
|
-
width: PropTypes.number.isRequired,
|
|
9
|
-
}).isRequired),
|
|
10
|
-
});
|
|
11
|
-
export const SlideTypesPropTypes = [ImageSlidePropTypes];
|
|
12
|
-
export const LightboxPropTypes = {
|
|
13
|
-
open: PropTypes.bool.isRequired,
|
|
14
|
-
close: PropTypes.func.isRequired,
|
|
15
|
-
index: PropTypes.number.isRequired,
|
|
16
|
-
slides: PropTypes.arrayOf(PropTypes.oneOfType(SlideTypesPropTypes).isRequired).isRequired,
|
|
17
|
-
render: PropTypes.shape({
|
|
18
|
-
slide: PropTypes.func,
|
|
19
|
-
slideHeader: PropTypes.func,
|
|
20
|
-
slideFooter: PropTypes.func,
|
|
21
|
-
slideContainer: PropTypes.func,
|
|
22
|
-
iconPrev: PropTypes.func,
|
|
23
|
-
iconNext: PropTypes.func,
|
|
24
|
-
iconClose: PropTypes.func,
|
|
25
|
-
iconLoading: PropTypes.func,
|
|
26
|
-
iconError: PropTypes.func,
|
|
27
|
-
buttonPrev: PropTypes.func,
|
|
28
|
-
buttonNext: PropTypes.func,
|
|
29
|
-
buttonClose: PropTypes.func,
|
|
30
|
-
}).isRequired,
|
|
31
|
-
plugins: PropTypes.arrayOf(PropTypes.func.isRequired).isRequired,
|
|
32
|
-
toolbar: PropTypes.shape({
|
|
33
|
-
buttons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.oneOf(["close"]), PropTypes.node])).isRequired,
|
|
34
|
-
}).isRequired,
|
|
35
|
-
labels: PropTypes.shape({}).isRequired,
|
|
36
|
-
carousel: PropTypes.shape({
|
|
37
|
-
finite: PropTypes.bool.isRequired,
|
|
38
|
-
preload: PropTypes.number.isRequired,
|
|
39
|
-
padding: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
|
|
40
|
-
spacing: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
|
|
41
|
-
}).isRequired,
|
|
42
|
-
animation: PropTypes.shape({
|
|
43
|
-
fade: PropTypes.number.isRequired,
|
|
44
|
-
swipe: PropTypes.number.isRequired,
|
|
45
|
-
}).isRequired,
|
|
46
|
-
controller: PropTypes.shape({
|
|
47
|
-
focus: PropTypes.bool.isRequired,
|
|
48
|
-
}).isRequired,
|
|
49
|
-
on: PropTypes.shape({
|
|
50
|
-
view: PropTypes.func,
|
|
51
|
-
entering: PropTypes.func,
|
|
52
|
-
entered: PropTypes.func,
|
|
53
|
-
exiting: PropTypes.func,
|
|
54
|
-
exited: PropTypes.func,
|
|
55
|
-
}).isRequired,
|
|
56
|
-
};
|
|
57
1
|
export const LightboxDefaultProps = {
|
|
58
2
|
open: false,
|
|
59
3
|
close: () => { },
|
|
@@ -72,6 +16,7 @@ export const LightboxDefaultProps = {
|
|
|
72
16
|
preload: 2,
|
|
73
17
|
padding: "16px",
|
|
74
18
|
spacing: "30%",
|
|
19
|
+
imageFit: "contain",
|
|
75
20
|
},
|
|
76
21
|
controller: {
|
|
77
22
|
focus: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yet-another-react-lightbox",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Modern React lightbox component",
|
|
5
5
|
"author": "Igor Danchenko",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"./plugins/captions.css": "./dist/plugins/captions.css",
|
|
15
15
|
"./plugins/fullscreen": "./dist/plugins/Fullscreen.js",
|
|
16
16
|
"./plugins/inline": "./dist/plugins/Inline.js",
|
|
17
|
+
"./plugins/slideshow": "./dist/plugins/Slideshow.js",
|
|
17
18
|
"./plugins/video": "./dist/plugins/Video.js",
|
|
18
19
|
"./styles.css": "./dist/styles.css"
|
|
19
20
|
},
|
|
@@ -38,6 +39,9 @@
|
|
|
38
39
|
"plugins/inline": [
|
|
39
40
|
"dist/plugins/Inline.d.ts"
|
|
40
41
|
],
|
|
42
|
+
"plugins/slideshow": [
|
|
43
|
+
"dist/plugins/Slideshow.d.ts"
|
|
44
|
+
],
|
|
41
45
|
"plugins/video": [
|
|
42
46
|
"dist/plugins/Video.d.ts"
|
|
43
47
|
]
|
|
@@ -70,9 +74,6 @@
|
|
|
70
74
|
"lint": "eslint .",
|
|
71
75
|
"test": "jest"
|
|
72
76
|
},
|
|
73
|
-
"dependencies": {
|
|
74
|
-
"prop-types": "^15.5.7"
|
|
75
|
-
},
|
|
76
77
|
"peerDependencies": {
|
|
77
78
|
"react": ">=16.8.0",
|
|
78
79
|
"react-dom": ">=16.8.0"
|
|
@@ -88,8 +89,8 @@
|
|
|
88
89
|
"@types/jest": "^28.1.1",
|
|
89
90
|
"@types/react": "^18.0.12",
|
|
90
91
|
"@types/react-dom": "^18.0.5",
|
|
91
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
92
|
-
"@typescript-eslint/parser": "^5.
|
|
92
|
+
"@typescript-eslint/eslint-plugin": "^5.28.0",
|
|
93
|
+
"@typescript-eslint/parser": "^5.28.0",
|
|
93
94
|
"autoprefixer": "^10.4.7",
|
|
94
95
|
"eslint": "^8.17.0",
|
|
95
96
|
"eslint-config-airbnb": "^19.0.4",
|
|
@@ -99,7 +100,7 @@
|
|
|
99
100
|
"eslint-plugin-jsx-a11y": "^6.5.1",
|
|
100
101
|
"eslint-plugin-prettier": "^4.0.0",
|
|
101
102
|
"eslint-plugin-react": "^7.30.0",
|
|
102
|
-
"eslint-plugin-react-hooks": "^4.
|
|
103
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
103
104
|
"husky": "^8.0.1",
|
|
104
105
|
"jest": "^28.1.1",
|
|
105
106
|
"jest-environment-jsdom": "^28.1.1",
|
|
@@ -107,12 +108,12 @@
|
|
|
107
108
|
"npm-run-all": "^4.1.5",
|
|
108
109
|
"postcss": "^8.4.14",
|
|
109
110
|
"postcss-cli": "^9.1.0",
|
|
110
|
-
"prettier": "^2.
|
|
111
|
-
"react": "^18.
|
|
112
|
-
"react-dom": "^18.
|
|
111
|
+
"prettier": "^2.7.0",
|
|
112
|
+
"react": "^18.2.0",
|
|
113
|
+
"react-dom": "^18.2.0",
|
|
113
114
|
"rimraf": "^3.0.2",
|
|
114
115
|
"sass": "^1.52.3",
|
|
115
|
-
"ts-jest": "^28.0.
|
|
116
|
+
"ts-jest": "^28.0.5",
|
|
116
117
|
"typescript": "^4.7.3"
|
|
117
118
|
},
|
|
118
119
|
"keywords": [
|