react-image-gallery 1.2.11 → 1.3.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/.eslintrc.json +42 -19
- package/.github/workflows/eslint.yml +56 -0
- package/README.md +161 -159
- package/babel.config.js +3 -0
- package/build/image-gallery.js +1 -1
- package/jest.config.js +16 -0
- package/package.json +20 -16
- package/src/{ImageGallery.js → components/ImageGallery.jsx} +443 -353
- package/src/components/ImageGallery.test.jsx +22 -0
- package/src/components/Item.jsx +75 -0
- package/src/{SVG.js → components/SVG.jsx} +16 -22
- package/src/{SwipeWrapper.js → components/SwipeWrapper.jsx} +15 -22
- package/src/{controls/Fullscreen.js → components/controls/Fullscreen.jsx} +6 -10
- package/src/{controls/LeftNav.js → components/controls/LeftNav.jsx} +5 -9
- package/src/{controls/PlayPause.js → components/controls/PlayPause.jsx} +6 -10
- package/src/{controls/RightNav.js → components/controls/RightNav.jsx} +5 -9
- package/styles/css/image-gallery.css +1 -1
- package/styles/scss/image-gallery.scss +10 -10
- package/webpack.build.js +61 -62
- package/webpack.config.js +18 -15
- package/.babelrc +0 -1
- package/.notes +0 -2
- package/src/Item.js +0 -78
- package/tests/ImageGallery.test.js +0 -15
- package/tests/__snapshots__/ImageGallery.test.js.snap +0 -3
- package/tests/setupTestFramework.js +0 -4
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
|
|
4
|
+
import ImageGallery from "./ImageGallery";
|
|
5
|
+
|
|
6
|
+
describe("<ImageGallery />", () => {
|
|
7
|
+
const defaultProps = {
|
|
8
|
+
items: [
|
|
9
|
+
{
|
|
10
|
+
original: "test.png",
|
|
11
|
+
thumbnail: "test_thumb.png",
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
it("renders slides", () => {
|
|
17
|
+
render(<ImageGallery {...defaultProps} />);
|
|
18
|
+
const elements = screen.getAllByLabelText("Go to Slide 1");
|
|
19
|
+
// expect a thumbnail and slide label
|
|
20
|
+
expect(elements.length).toBe(2);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { bool, func, string } from "prop-types";
|
|
3
|
+
|
|
4
|
+
const defaultProps = {
|
|
5
|
+
description: "",
|
|
6
|
+
fullscreen: "",
|
|
7
|
+
isFullscreen: false,
|
|
8
|
+
originalAlt: "",
|
|
9
|
+
originalHeight: "",
|
|
10
|
+
originalWidth: "",
|
|
11
|
+
originalTitle: "",
|
|
12
|
+
sizes: "",
|
|
13
|
+
srcSet: "",
|
|
14
|
+
loading: "eager",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const Item = React.memo((props) => {
|
|
18
|
+
const {
|
|
19
|
+
description,
|
|
20
|
+
fullscreen, // fullscreen version of img
|
|
21
|
+
handleImageLoaded,
|
|
22
|
+
isFullscreen,
|
|
23
|
+
onImageError,
|
|
24
|
+
original,
|
|
25
|
+
originalAlt,
|
|
26
|
+
originalHeight,
|
|
27
|
+
originalWidth,
|
|
28
|
+
originalTitle,
|
|
29
|
+
sizes,
|
|
30
|
+
srcSet,
|
|
31
|
+
loading,
|
|
32
|
+
} = { ...defaultProps, ...props };
|
|
33
|
+
const itemSrc = isFullscreen ? fullscreen || original : original;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<React.Fragment>
|
|
37
|
+
<img
|
|
38
|
+
className="image-gallery-image"
|
|
39
|
+
src={itemSrc}
|
|
40
|
+
alt={originalAlt}
|
|
41
|
+
srcSet={srcSet}
|
|
42
|
+
height={originalHeight}
|
|
43
|
+
width={originalWidth}
|
|
44
|
+
sizes={sizes}
|
|
45
|
+
title={originalTitle}
|
|
46
|
+
onLoad={(event) => handleImageLoaded(event, original)}
|
|
47
|
+
onError={onImageError}
|
|
48
|
+
loading={loading}
|
|
49
|
+
/>
|
|
50
|
+
{description && (
|
|
51
|
+
<span className="image-gallery-description">{description}</span>
|
|
52
|
+
)}
|
|
53
|
+
</React.Fragment>
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
Item.displayName = "Item";
|
|
58
|
+
|
|
59
|
+
Item.propTypes = {
|
|
60
|
+
description: string,
|
|
61
|
+
fullscreen: string, // fullscreen version of img
|
|
62
|
+
handleImageLoaded: func.isRequired,
|
|
63
|
+
isFullscreen: bool,
|
|
64
|
+
onImageError: func.isRequired,
|
|
65
|
+
original: string.isRequired,
|
|
66
|
+
originalAlt: string,
|
|
67
|
+
originalHeight: string,
|
|
68
|
+
originalWidth: string,
|
|
69
|
+
originalTitle: string,
|
|
70
|
+
sizes: string,
|
|
71
|
+
srcSet: string,
|
|
72
|
+
loading: string,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export default Item;
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { number, oneOf, string } from
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { number, oneOf, string } from "prop-types";
|
|
3
3
|
|
|
4
4
|
const left = <polyline points="15 18 9 12 15 6" />;
|
|
5
5
|
const right = <polyline points="9 18 15 12 9 6" />;
|
|
6
|
-
const maximize =
|
|
7
|
-
|
|
6
|
+
const maximize = (
|
|
7
|
+
<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" />
|
|
8
|
+
);
|
|
9
|
+
const minimize = (
|
|
10
|
+
<path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3" />
|
|
11
|
+
);
|
|
8
12
|
const play = <polygon points="5 3 19 12 5 21 5 3" />;
|
|
9
13
|
const pause = (
|
|
10
14
|
<React.Fragment>
|
|
@@ -22,12 +26,13 @@ const iconMapper = {
|
|
|
22
26
|
pause,
|
|
23
27
|
};
|
|
24
28
|
|
|
29
|
+
const defaultProps = {
|
|
30
|
+
strokeWidth: 1,
|
|
31
|
+
viewBox: "0 0 24 24",
|
|
32
|
+
};
|
|
33
|
+
|
|
25
34
|
const SVG = (props) => {
|
|
26
|
-
const {
|
|
27
|
-
strokeWidth,
|
|
28
|
-
viewBox,
|
|
29
|
-
icon,
|
|
30
|
-
} = props;
|
|
35
|
+
const { strokeWidth, viewBox, icon } = { ...defaultProps, ...props };
|
|
31
36
|
return (
|
|
32
37
|
<svg
|
|
33
38
|
className="image-gallery-svg"
|
|
@@ -47,19 +52,8 @@ const SVG = (props) => {
|
|
|
47
52
|
SVG.propTypes = {
|
|
48
53
|
strokeWidth: number,
|
|
49
54
|
viewBox: string,
|
|
50
|
-
icon: oneOf([
|
|
51
|
-
|
|
52
|
-
'right',
|
|
53
|
-
'maximize',
|
|
54
|
-
'minimize',
|
|
55
|
-
'play',
|
|
56
|
-
'pause',
|
|
57
|
-
]).isRequired,
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
SVG.defaultProps = {
|
|
61
|
-
strokeWidth: 1,
|
|
62
|
-
viewBox: '0 0 24 24',
|
|
55
|
+
icon: oneOf(["left", "right", "maximize", "minimize", "play", "pause"])
|
|
56
|
+
.isRequired,
|
|
63
57
|
};
|
|
64
58
|
|
|
65
59
|
export default SVG;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
node,
|
|
5
|
-
number,
|
|
6
|
-
func,
|
|
7
|
-
} from 'prop-types';
|
|
8
|
-
import { useSwipeable } from 'react-swipeable';
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { string, node, number, func } from "prop-types";
|
|
3
|
+
import { useSwipeable } from "react-swipeable";
|
|
9
4
|
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
5
|
+
const defaultProps = {
|
|
6
|
+
className: "",
|
|
7
|
+
delta: 0,
|
|
8
|
+
onSwiping: () => {},
|
|
9
|
+
onSwiped: () => {},
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const SwipeWrapper = (props) => {
|
|
13
|
+
const { children, className, delta, onSwiping, onSwiped } = {
|
|
14
|
+
...defaultProps,
|
|
15
|
+
...props,
|
|
16
|
+
};
|
|
17
17
|
const swipeHandlers = useSwipeable({
|
|
18
18
|
delta,
|
|
19
19
|
onSwiping,
|
|
@@ -34,11 +34,4 @@ SwipeWrapper.propTypes = {
|
|
|
34
34
|
onSwiping: func,
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
SwipeWrapper.defaultProps = {
|
|
38
|
-
className: '',
|
|
39
|
-
delta: 0,
|
|
40
|
-
onSwiping: () => {},
|
|
41
|
-
onSwiped: () => {},
|
|
42
|
-
};
|
|
43
|
-
|
|
44
37
|
export default SwipeWrapper;
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { bool, func } from
|
|
3
|
-
import SVG from
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { bool, func } from "prop-types";
|
|
3
|
+
import SVG from "src/components/SVG";
|
|
4
4
|
|
|
5
|
-
const Fullscreen = React.memo(({
|
|
6
|
-
isFullscreen,
|
|
7
|
-
onClick,
|
|
8
|
-
}) => {
|
|
5
|
+
const Fullscreen = React.memo(({ isFullscreen, onClick }) => {
|
|
9
6
|
return (
|
|
10
7
|
<button
|
|
11
8
|
type="button"
|
|
@@ -13,17 +10,16 @@ const Fullscreen = React.memo(({
|
|
|
13
10
|
onClick={onClick}
|
|
14
11
|
aria-label="Open Fullscreen"
|
|
15
12
|
>
|
|
16
|
-
<SVG strokeWidth={2} icon={isFullscreen ?
|
|
13
|
+
<SVG strokeWidth={2} icon={isFullscreen ? "minimize" : "maximize"} />
|
|
17
14
|
</button>
|
|
18
15
|
);
|
|
19
16
|
});
|
|
20
17
|
|
|
21
|
-
Fullscreen.displayName =
|
|
18
|
+
Fullscreen.displayName = "Fullscreen";
|
|
22
19
|
|
|
23
20
|
Fullscreen.propTypes = {
|
|
24
21
|
isFullscreen: bool.isRequired,
|
|
25
22
|
onClick: func.isRequired,
|
|
26
23
|
};
|
|
27
24
|
|
|
28
|
-
|
|
29
25
|
export default Fullscreen;
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { bool, func } from
|
|
3
|
-
import SVG from
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { bool, func } from "prop-types";
|
|
3
|
+
import SVG from "src/components/SVG";
|
|
4
4
|
|
|
5
|
-
const LeftNav = React.memo(({
|
|
6
|
-
disabled,
|
|
7
|
-
onClick,
|
|
8
|
-
}) => {
|
|
5
|
+
const LeftNav = React.memo(({ disabled, onClick }) => {
|
|
9
6
|
return (
|
|
10
7
|
<button
|
|
11
8
|
type="button"
|
|
@@ -19,12 +16,11 @@ const LeftNav = React.memo(({
|
|
|
19
16
|
);
|
|
20
17
|
});
|
|
21
18
|
|
|
22
|
-
LeftNav.displayName =
|
|
19
|
+
LeftNav.displayName = "LeftNav";
|
|
23
20
|
|
|
24
21
|
LeftNav.propTypes = {
|
|
25
22
|
disabled: bool.isRequired,
|
|
26
23
|
onClick: func.isRequired,
|
|
27
24
|
};
|
|
28
25
|
|
|
29
|
-
|
|
30
26
|
export default LeftNav;
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { bool, func } from
|
|
3
|
-
import SVG from
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { bool, func } from "prop-types";
|
|
3
|
+
import SVG from "src/components/SVG";
|
|
4
4
|
|
|
5
|
-
const PlayPause = React.memo(({
|
|
6
|
-
isPlaying,
|
|
7
|
-
onClick,
|
|
8
|
-
}) => {
|
|
5
|
+
const PlayPause = React.memo(({ isPlaying, onClick }) => {
|
|
9
6
|
return (
|
|
10
7
|
<button
|
|
11
8
|
type="button"
|
|
@@ -13,17 +10,16 @@ const PlayPause = React.memo(({
|
|
|
13
10
|
onClick={onClick}
|
|
14
11
|
aria-label="Play or Pause Slideshow"
|
|
15
12
|
>
|
|
16
|
-
<SVG strokeWidth={2} icon={isPlaying ?
|
|
13
|
+
<SVG strokeWidth={2} icon={isPlaying ? "pause" : "play"} />
|
|
17
14
|
</button>
|
|
18
15
|
);
|
|
19
16
|
});
|
|
20
17
|
|
|
21
|
-
PlayPause.displayName =
|
|
18
|
+
PlayPause.displayName = "PlayPause";
|
|
22
19
|
|
|
23
20
|
PlayPause.propTypes = {
|
|
24
21
|
isPlaying: bool.isRequired,
|
|
25
22
|
onClick: func.isRequired,
|
|
26
23
|
};
|
|
27
24
|
|
|
28
|
-
|
|
29
25
|
export default PlayPause;
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { bool, func } from
|
|
3
|
-
import SVG from
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { bool, func } from "prop-types";
|
|
3
|
+
import SVG from "src/components/SVG";
|
|
4
4
|
|
|
5
|
-
const RightNav = React.memo(({
|
|
6
|
-
disabled,
|
|
7
|
-
onClick,
|
|
8
|
-
}) => {
|
|
5
|
+
const RightNav = React.memo(({ disabled, onClick }) => {
|
|
9
6
|
return (
|
|
10
7
|
<button
|
|
11
8
|
type="button"
|
|
@@ -19,12 +16,11 @@ const RightNav = React.memo(({
|
|
|
19
16
|
);
|
|
20
17
|
});
|
|
21
18
|
|
|
22
|
-
RightNav.displayName =
|
|
19
|
+
RightNav.displayName = "RightNav";
|
|
23
20
|
|
|
24
21
|
RightNav.propTypes = {
|
|
25
22
|
disabled: bool.isRequired,
|
|
26
23
|
onClick: func.isRequired,
|
|
27
24
|
};
|
|
28
25
|
|
|
29
|
-
|
|
30
26
|
export default RightNav;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.image-gallery-icon{color:#fff;transition:all .3s ease-out;appearance:none;background-color:transparent;border:0;cursor:pointer;outline:none;position:absolute;z-index:4;filter:drop-shadow(0 2px 2px #1a1a1a)}@media(hover: hover)and (pointer: fine){.image-gallery-icon:hover{color:#337ab7}.image-gallery-icon:hover .image-gallery-svg{transform:scale(1.1)}}.image-gallery-icon:focus{outline:2px solid #337ab7}.image-gallery-using-mouse .image-gallery-icon:focus{outline:none}.image-gallery-fullscreen-button,.image-gallery-play-button{bottom:0;padding:20px}.image-gallery-fullscreen-button .image-gallery-svg,.image-gallery-play-button .image-gallery-svg{height:28px;width:28px}@media(max-width: 768px){.image-gallery-fullscreen-button,.image-gallery-play-button{padding:15px}.image-gallery-fullscreen-button .image-gallery-svg,.image-gallery-play-button .image-gallery-svg{height:24px;width:24px}}@media(max-width: 480px){.image-gallery-fullscreen-button,.image-gallery-play-button{padding:10px}.image-gallery-fullscreen-button .image-gallery-svg,.image-gallery-play-button .image-gallery-svg{height:16px;width:16px}}.image-gallery-fullscreen-button{right:0}.image-gallery-play-button{left:0}.image-gallery-left-nav,.image-gallery-right-nav{padding:50px 10px;top:50%;transform:translateY(-50%)}.image-gallery-left-nav .image-gallery-svg,.image-gallery-right-nav .image-gallery-svg{height:120px;width:60px}@media(max-width: 768px){.image-gallery-left-nav .image-gallery-svg,.image-gallery-right-nav .image-gallery-svg{height:72px;width:36px}}@media(max-width: 480px){.image-gallery-left-nav .image-gallery-svg,.image-gallery-right-nav .image-gallery-svg{height:48px;width:24px}}.image-gallery-left-nav[disabled],.image-gallery-right-nav[disabled]{cursor:disabled;opacity:.6;pointer-events:none}.image-gallery-left-nav{left:0}.image-gallery-right-nav{right:0}.image-gallery{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;-webkit-tap-highlight-color:rgba(0,0,0,0);position:relative}.image-gallery.fullscreen-modal{background:#000;bottom:0;height:100%;left:0;position:fixed;right:0;top:0;width:100%;z-index:5}.image-gallery.fullscreen-modal .image-gallery-content{top:50%;transform:translateY(-50%)}.image-gallery-content{position:relative;line-height:0;top:0}.image-gallery-content.fullscreen{background:#000}.image-gallery-content .image-gallery-slide .image-gallery-image{max-height:calc(100vh - 80px)}.image-gallery-content.left .image-gallery-slide .image-gallery-image,.image-gallery-content.right .image-gallery-slide .image-gallery-image{max-height:100vh}.image-gallery-slide-wrapper{position:relative}.image-gallery-slide-wrapper.left,.image-gallery-slide-wrapper.right{display:inline-block;width:calc(100% - 110px)}@media(max-width: 768px){.image-gallery-slide-wrapper.left,.image-gallery-slide-wrapper.right{width:calc(100% - 87px)}}.image-gallery-slide-wrapper.image-gallery-rtl{direction:rtl}.image-gallery-slides{line-height:0;overflow:hidden;position:relative;white-space:nowrap;text-align:center}.image-gallery-slide{left:0;position:absolute;top:0;width:100%}.image-gallery-slide.center{position:relative}.image-gallery-slide .image-gallery-image{width:100%;object-fit:contain}.image-gallery-slide .image-gallery-description{background:rgba(0,0,0,.4);bottom:70px;color:#fff;left:0;line-height:1;padding:10px 20px;position:absolute;white-space:normal}@media(max-width: 768px){.image-gallery-slide .image-gallery-description{bottom:45px;font-size:.8em;padding:8px 15px}}.image-gallery-bullets{bottom:20px;left:0;margin:0 auto;position:absolute;right:0;width:80%;z-index:4}.image-gallery-bullets .image-gallery-bullets-container{margin:0;padding:0;text-align:center}.image-gallery-bullets .image-gallery-bullet{appearance:none;background-color:transparent;border:1px solid #fff;border-radius:50%;box-shadow:0 2px 2px #1a1a1a;cursor:pointer;display:inline-block;margin:0 5px;outline:none;padding:5px;transition:all .2s ease-out}@media(max-width: 768px){.image-gallery-bullets .image-gallery-bullet{margin:0 3px;padding:3px}}@media(max-width: 480px){.image-gallery-bullets .image-gallery-bullet{padding:2.7px}}.image-gallery-bullets .image-gallery-bullet:focus{transform:scale(1.2);background:#337ab7;border:1px solid #337ab7}.image-gallery-bullets .image-gallery-bullet.active{transform:scale(1.2);border:1px solid #fff;background:#fff}@media(hover: hover)and (pointer: fine){.image-gallery-bullets .image-gallery-bullet:hover{background:#337ab7;border:1px solid #337ab7}.image-gallery-bullets .image-gallery-bullet.active:hover{background:#337ab7}}.image-gallery-thumbnails-wrapper{position:relative}.image-gallery-thumbnails-wrapper.thumbnails-swipe-horizontal{touch-action:pan-y}.image-gallery-thumbnails-wrapper.thumbnails-swipe-vertical{touch-action:pan-x}.image-gallery-thumbnails-wrapper.thumbnails-wrapper-rtl{direction:rtl}.image-gallery-thumbnails-wrapper.left,.image-gallery-thumbnails-wrapper.right{display:inline-block;vertical-align:top;width:100px}@media(max-width: 768px){.image-gallery-thumbnails-wrapper.left,.image-gallery-thumbnails-wrapper.right{width:81px}}.image-gallery-thumbnails-wrapper.left .image-gallery-thumbnails,.image-gallery-thumbnails-wrapper.right .image-gallery-thumbnails{height:100%;width:100%;left:0;padding:0;position:absolute;top:0}.image-gallery-thumbnails-wrapper.left .image-gallery-thumbnails .image-gallery-thumbnail,.image-gallery-thumbnails-wrapper.right .image-gallery-thumbnails .image-gallery-thumbnail{display:block;margin-right:0;padding:0}.image-gallery-thumbnails-wrapper.left .image-gallery-thumbnails .image-gallery-thumbnail+.image-gallery-thumbnail,.image-gallery-thumbnails-wrapper.right .image-gallery-thumbnails .image-gallery-thumbnail+.image-gallery-thumbnail{margin-left:0;margin-top:2px}.image-gallery-thumbnails-wrapper.left,.image-gallery-thumbnails-wrapper.right{margin:0 5px}@media(max-width: 768px){.image-gallery-thumbnails-wrapper.left,.image-gallery-thumbnails-wrapper.right{margin:0 3px}}.image-gallery-thumbnails{overflow:hidden;padding:5px 0}@media(max-width: 768px){.image-gallery-thumbnails{padding:3px 0}}.image-gallery-thumbnails .image-gallery-thumbnails-container{cursor:pointer;text-align:center;white-space:nowrap}.image-gallery-thumbnail{display:inline-block;border:4px solid transparent;transition:border .3s ease-out;width:100px;background:transparent;padding:0}@media(max-width: 768px){.image-gallery-thumbnail{border:3px solid transparent;width:81px}}.image-gallery-thumbnail+.image-gallery-thumbnail{margin-left:2px}.image-gallery-thumbnail .image-gallery-thumbnail-inner{display:block;position:relative}.image-gallery-thumbnail .image-gallery-thumbnail-image{vertical-align:middle;width:100%;line-height:0}.image-gallery-thumbnail.active,.image-gallery-thumbnail:focus{outline:none;border:4px solid #337ab7}@media(max-width: 768px){.image-gallery-thumbnail.active,.image-gallery-thumbnail:focus{border:3px solid #337ab7}}@media(hover: hover)and (pointer: fine){.image-gallery-thumbnail:hover{outline:none;border:4px solid #337ab7}}@media(hover: hover)and (pointer: fine)and (max-width: 768px){.image-gallery-thumbnail:hover{border:3px solid #337ab7}}.image-gallery-thumbnail-label{box-sizing:border-box;color:#fff;font-size:1em;left:0;line-height:1em;padding:5%;position:absolute;top:50%;text-shadow:0 2px 2px #1a1a1a;transform:translateY(-50%);white-space:normal;width:100%}@media(max-width: 768px){.image-gallery-thumbnail-label{font-size:.8em;line-height:.8em}}.image-gallery-index{background:rgba(0,0,0,.4);color:#fff;line-height:1;padding:10px 20px;position:absolute;right:0;top:0;z-index:4}@media(max-width: 768px){.image-gallery-index{font-size:.8em;padding:5px 10px}}
|
|
1
|
+
.image-gallery-icon{color:#fff;transition:all .3s ease-out;appearance:none;background-color:transparent;border:0;cursor:pointer;outline:none;position:absolute;z-index:4;filter:drop-shadow(0 2px 2px #1a1a1a)}@media(hover: hover)and (pointer: fine){.image-gallery-icon:hover{color:#337ab7}.image-gallery-icon:hover .image-gallery-svg{transform:scale(1.1)}}.image-gallery-icon:focus{outline:2px solid #337ab7}.image-gallery-using-mouse .image-gallery-icon:focus{outline:none}.image-gallery-fullscreen-button,.image-gallery-play-button{bottom:0;padding:20px}.image-gallery-fullscreen-button .image-gallery-svg,.image-gallery-play-button .image-gallery-svg{height:28px;width:28px}@media(max-width: 768px){.image-gallery-fullscreen-button,.image-gallery-play-button{padding:15px}.image-gallery-fullscreen-button .image-gallery-svg,.image-gallery-play-button .image-gallery-svg{height:24px;width:24px}}@media(max-width: 480px){.image-gallery-fullscreen-button,.image-gallery-play-button{padding:10px}.image-gallery-fullscreen-button .image-gallery-svg,.image-gallery-play-button .image-gallery-svg{height:16px;width:16px}}.image-gallery-fullscreen-button{right:0}.image-gallery-play-button{left:0}.image-gallery-left-nav,.image-gallery-right-nav{padding:50px 10px;top:50%;transform:translateY(-50%)}.image-gallery-left-nav .image-gallery-svg,.image-gallery-right-nav .image-gallery-svg{height:120px;width:60px}@media(max-width: 768px){.image-gallery-left-nav .image-gallery-svg,.image-gallery-right-nav .image-gallery-svg{height:72px;width:36px}}@media(max-width: 480px){.image-gallery-left-nav .image-gallery-svg,.image-gallery-right-nav .image-gallery-svg{height:48px;width:24px}}.image-gallery-left-nav[disabled],.image-gallery-right-nav[disabled]{cursor:disabled;opacity:.6;pointer-events:none}.image-gallery-left-nav{left:0}.image-gallery-right-nav{right:0}.image-gallery{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;-webkit-tap-highlight-color:rgba(0,0,0,0);position:relative}.image-gallery.fullscreen-modal{background:#000;bottom:0;height:100%;left:0;position:fixed;right:0;top:0;width:100%;z-index:5}.image-gallery.fullscreen-modal .image-gallery-content{top:50%;transform:translateY(-50%)}.image-gallery-content{position:relative;line-height:0;top:0}.image-gallery-content.fullscreen{background:#000}.image-gallery-content .image-gallery-slide .image-gallery-image{max-height:calc(100vh - 80px)}.image-gallery-content.image-gallery-thumbnails-left .image-gallery-slide .image-gallery-image,.image-gallery-content.image-gallery-thumbnails-right .image-gallery-slide .image-gallery-image{max-height:100vh}.image-gallery-slide-wrapper{position:relative}.image-gallery-slide-wrapper.image-gallery-thumbnails-left,.image-gallery-slide-wrapper.image-gallery-thumbnails-right{display:inline-block;width:calc(100% - 110px)}@media(max-width: 768px){.image-gallery-slide-wrapper.image-gallery-thumbnails-left,.image-gallery-slide-wrapper.image-gallery-thumbnails-right{width:calc(100% - 87px)}}.image-gallery-slide-wrapper.image-gallery-rtl{direction:rtl}.image-gallery-slides{line-height:0;overflow:hidden;position:relative;white-space:nowrap;text-align:center}.image-gallery-slide{left:0;position:absolute;top:0;width:100%}.image-gallery-slide.image-gallery-center{position:relative}.image-gallery-slide .image-gallery-image{width:100%;object-fit:contain}.image-gallery-slide .image-gallery-description{background:rgba(0,0,0,.4);bottom:70px;color:#fff;left:0;line-height:1;padding:10px 20px;position:absolute;white-space:normal}@media(max-width: 768px){.image-gallery-slide .image-gallery-description{bottom:45px;font-size:.8em;padding:8px 15px}}.image-gallery-bullets{bottom:20px;left:0;margin:0 auto;position:absolute;right:0;width:80%;z-index:4}.image-gallery-bullets .image-gallery-bullets-container{margin:0;padding:0;text-align:center}.image-gallery-bullets .image-gallery-bullet{appearance:none;background-color:transparent;border:1px solid #fff;border-radius:50%;box-shadow:0 2px 2px #1a1a1a;cursor:pointer;display:inline-block;margin:0 5px;outline:none;padding:5px;transition:all .2s ease-out}@media(max-width: 768px){.image-gallery-bullets .image-gallery-bullet{margin:0 3px;padding:3px}}@media(max-width: 480px){.image-gallery-bullets .image-gallery-bullet{padding:2.7px}}.image-gallery-bullets .image-gallery-bullet:focus{transform:scale(1.2);background:#337ab7;border:1px solid #337ab7}.image-gallery-bullets .image-gallery-bullet.active{transform:scale(1.2);border:1px solid #fff;background:#fff}@media(hover: hover)and (pointer: fine){.image-gallery-bullets .image-gallery-bullet:hover{background:#337ab7;border:1px solid #337ab7}.image-gallery-bullets .image-gallery-bullet.active:hover{background:#337ab7}}.image-gallery-thumbnails-wrapper{position:relative}.image-gallery-thumbnails-wrapper.thumbnails-swipe-horizontal{touch-action:pan-y}.image-gallery-thumbnails-wrapper.thumbnails-swipe-vertical{touch-action:pan-x}.image-gallery-thumbnails-wrapper.thumbnails-wrapper-rtl{direction:rtl}.image-gallery-thumbnails-wrapper.image-gallery-thumbnails-left,.image-gallery-thumbnails-wrapper.image-gallery-thumbnails-right{display:inline-block;vertical-align:top;width:100px}@media(max-width: 768px){.image-gallery-thumbnails-wrapper.image-gallery-thumbnails-left,.image-gallery-thumbnails-wrapper.image-gallery-thumbnails-right{width:81px}}.image-gallery-thumbnails-wrapper.image-gallery-thumbnails-left .image-gallery-thumbnails,.image-gallery-thumbnails-wrapper.image-gallery-thumbnails-right .image-gallery-thumbnails{height:100%;width:100%;left:0;padding:0;position:absolute;top:0}.image-gallery-thumbnails-wrapper.image-gallery-thumbnails-left .image-gallery-thumbnails .image-gallery-thumbnail,.image-gallery-thumbnails-wrapper.image-gallery-thumbnails-right .image-gallery-thumbnails .image-gallery-thumbnail{display:block;margin-right:0;padding:0}.image-gallery-thumbnails-wrapper.image-gallery-thumbnails-left .image-gallery-thumbnails .image-gallery-thumbnail+.image-gallery-thumbnail,.image-gallery-thumbnails-wrapper.image-gallery-thumbnails-right .image-gallery-thumbnails .image-gallery-thumbnail+.image-gallery-thumbnail{margin-left:0;margin-top:2px}.image-gallery-thumbnails-wrapper.image-gallery-thumbnails-left,.image-gallery-thumbnails-wrapper.image-gallery-thumbnails-right{margin:0 5px}@media(max-width: 768px){.image-gallery-thumbnails-wrapper.image-gallery-thumbnails-left,.image-gallery-thumbnails-wrapper.image-gallery-thumbnails-right{margin:0 3px}}.image-gallery-thumbnails{overflow:hidden;padding:5px 0}@media(max-width: 768px){.image-gallery-thumbnails{padding:3px 0}}.image-gallery-thumbnails .image-gallery-thumbnails-container{cursor:pointer;text-align:center;white-space:nowrap}.image-gallery-thumbnail{display:inline-block;border:4px solid transparent;transition:border .3s ease-out;width:100px;background:transparent;padding:0}@media(max-width: 768px){.image-gallery-thumbnail{border:3px solid transparent;width:81px}}.image-gallery-thumbnail+.image-gallery-thumbnail{margin-left:2px}.image-gallery-thumbnail .image-gallery-thumbnail-inner{display:block;position:relative}.image-gallery-thumbnail .image-gallery-thumbnail-image{vertical-align:middle;width:100%;line-height:0}.image-gallery-thumbnail.active,.image-gallery-thumbnail:focus{outline:none;border:4px solid #337ab7}@media(max-width: 768px){.image-gallery-thumbnail.active,.image-gallery-thumbnail:focus{border:3px solid #337ab7}}@media(hover: hover)and (pointer: fine){.image-gallery-thumbnail:hover{outline:none;border:4px solid #337ab7}}@media(hover: hover)and (pointer: fine)and (max-width: 768px){.image-gallery-thumbnail:hover{border:3px solid #337ab7}}.image-gallery-thumbnail-label{box-sizing:border-box;color:#fff;font-size:1em;left:0;line-height:1em;padding:5%;position:absolute;top:50%;text-shadow:0 2px 2px #1a1a1a;transform:translateY(-50%);white-space:normal;width:100%}@media(max-width: 768px){.image-gallery-thumbnail-label{font-size:.8em;line-height:.8em}}.image-gallery-index{background:rgba(0,0,0,.4);color:#fff;line-height:1;padding:10px 20px;position:absolute;right:0;top:0;z-index:4}@media(max-width: 768px){.image-gallery-index{font-size:.8em;padding:5px 10px}}
|
|
@@ -163,8 +163,8 @@ $ig-shadow: 0 2px 2px lighten($ig-black, 10%);
|
|
|
163
163
|
max-height: calc(100vh - 80px); // 80 px for the thumbnail space
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
&.left,
|
|
167
|
-
&.right {
|
|
166
|
+
&.image-gallery-thumbnails-left,
|
|
167
|
+
&.image-gallery-thumbnails-right {
|
|
168
168
|
.image-gallery-slide .image-gallery-image {
|
|
169
169
|
max-height: 100vh;
|
|
170
170
|
}
|
|
@@ -174,8 +174,8 @@ $ig-shadow: 0 2px 2px lighten($ig-black, 10%);
|
|
|
174
174
|
.image-gallery-slide-wrapper {
|
|
175
175
|
position: relative;
|
|
176
176
|
|
|
177
|
-
&.left,
|
|
178
|
-
&.right {
|
|
177
|
+
&.image-gallery-thumbnails-left,
|
|
178
|
+
&.image-gallery-thumbnails-right {
|
|
179
179
|
display: inline-block;
|
|
180
180
|
width: calc(100% - 110px); // 100px + 10px for margin
|
|
181
181
|
|
|
@@ -202,7 +202,7 @@ $ig-shadow: 0 2px 2px lighten($ig-black, 10%);
|
|
|
202
202
|
top: 0;
|
|
203
203
|
width: 100%;
|
|
204
204
|
|
|
205
|
-
&.center {
|
|
205
|
+
&.image-gallery-center {
|
|
206
206
|
position: relative;
|
|
207
207
|
}
|
|
208
208
|
|
|
@@ -306,8 +306,8 @@ $ig-shadow: 0 2px 2px lighten($ig-black, 10%);
|
|
|
306
306
|
&.thumbnails-wrapper-rtl {
|
|
307
307
|
direction: rtl;
|
|
308
308
|
}
|
|
309
|
-
&.left,
|
|
310
|
-
&.right {
|
|
309
|
+
&.image-gallery-thumbnails-left,
|
|
310
|
+
&.image-gallery-thumbnails-right {
|
|
311
311
|
display: inline-block;
|
|
312
312
|
vertical-align: top;
|
|
313
313
|
width: 100px;
|
|
@@ -339,8 +339,8 @@ $ig-shadow: 0 2px 2px lighten($ig-black, 10%);
|
|
|
339
339
|
}
|
|
340
340
|
}
|
|
341
341
|
|
|
342
|
-
&.left,
|
|
343
|
-
&.right {
|
|
342
|
+
&.image-gallery-thumbnails-left,
|
|
343
|
+
&.image-gallery-thumbnails-right {
|
|
344
344
|
margin: 0 5px;
|
|
345
345
|
|
|
346
346
|
@media (max-width: $ig-small-screen) {
|
|
@@ -450,4 +450,4 @@ $ig-shadow: 0 2px 2px lighten($ig-black, 10%);
|
|
|
450
450
|
font-size: .8em;
|
|
451
451
|
padding: 5px 10px;
|
|
452
452
|
}
|
|
453
|
-
}
|
|
453
|
+
}
|
package/webpack.build.js
CHANGED
|
@@ -1,57 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const RemovePlugin = require('remove-files-webpack-plugin');
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
|
3
|
+
const RemovePlugin = require("remove-files-webpack-plugin");
|
|
5
4
|
|
|
6
5
|
const config = {
|
|
7
|
-
mode:
|
|
6
|
+
mode: "production",
|
|
8
7
|
};
|
|
9
8
|
|
|
10
9
|
const jsOutput = Object.assign({}, config, {
|
|
11
|
-
entry: [
|
|
10
|
+
entry: ["./src/components/ImageGallery.jsx"],
|
|
12
11
|
output: {
|
|
13
|
-
path: path.resolve(__dirname,
|
|
14
|
-
filename:
|
|
15
|
-
library:
|
|
16
|
-
globalObject:
|
|
17
|
-
libraryTarget:
|
|
12
|
+
path: path.resolve(__dirname, "build"),
|
|
13
|
+
filename: "image-gallery.js",
|
|
14
|
+
library: "ImageGallery",
|
|
15
|
+
globalObject: "this",
|
|
16
|
+
libraryTarget: "umd",
|
|
18
17
|
},
|
|
19
18
|
resolve: {
|
|
20
19
|
alias: {
|
|
21
|
-
src: path.resolve(__dirname,
|
|
20
|
+
src: path.resolve(__dirname, "src/"),
|
|
22
21
|
},
|
|
23
|
-
extensions: [
|
|
22
|
+
extensions: [".js", ".jsx"],
|
|
24
23
|
},
|
|
25
24
|
module: {
|
|
26
25
|
rules: [
|
|
27
26
|
{
|
|
28
|
-
test: /\.js$/,
|
|
27
|
+
test: /\.(js|jsx)$/,
|
|
29
28
|
exclude: /node_modules/,
|
|
30
|
-
loader:
|
|
31
|
-
}
|
|
32
|
-
]
|
|
29
|
+
loader: "babel-loader",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
33
32
|
},
|
|
34
33
|
externals: {
|
|
35
34
|
// Don't bundle react or react-dom
|
|
36
35
|
react: {
|
|
37
|
-
commonjs:
|
|
38
|
-
commonjs2:
|
|
39
|
-
amd:
|
|
40
|
-
root:
|
|
36
|
+
commonjs: "react",
|
|
37
|
+
commonjs2: "react",
|
|
38
|
+
amd: "react",
|
|
39
|
+
root: "React",
|
|
41
40
|
},
|
|
42
|
-
|
|
43
|
-
commonjs:
|
|
44
|
-
commonjs2:
|
|
45
|
-
amd:
|
|
46
|
-
root:
|
|
41
|
+
"react-dom": {
|
|
42
|
+
commonjs: "react-dom",
|
|
43
|
+
commonjs2: "react-dom",
|
|
44
|
+
amd: "react-dom",
|
|
45
|
+
root: "ReactDOM",
|
|
47
46
|
},
|
|
48
47
|
},
|
|
49
48
|
});
|
|
50
49
|
|
|
51
50
|
const cssOutput = Object.assign({}, config, {
|
|
52
|
-
entry:
|
|
51
|
+
entry: "./styles/scss/image-gallery.scss",
|
|
53
52
|
output: {
|
|
54
|
-
path: path.resolve(__dirname,
|
|
53
|
+
path: path.resolve(__dirname, "styles/css"),
|
|
55
54
|
},
|
|
56
55
|
module: {
|
|
57
56
|
rules: [
|
|
@@ -60,16 +59,16 @@ const cssOutput = Object.assign({}, config, {
|
|
|
60
59
|
use: [
|
|
61
60
|
MiniCssExtractPlugin.loader,
|
|
62
61
|
// Translates CSS into CommonJS
|
|
63
|
-
|
|
62
|
+
"css-loader",
|
|
64
63
|
// Compiles Sass to CSS
|
|
65
|
-
|
|
64
|
+
"sass-loader",
|
|
66
65
|
],
|
|
67
|
-
}
|
|
68
|
-
]
|
|
66
|
+
},
|
|
67
|
+
],
|
|
69
68
|
},
|
|
70
69
|
plugins: [
|
|
71
70
|
new MiniCssExtractPlugin({
|
|
72
|
-
filename:
|
|
71
|
+
filename: "image-gallery.css",
|
|
73
72
|
}),
|
|
74
73
|
new RemovePlugin({
|
|
75
74
|
/**
|
|
@@ -78,36 +77,36 @@ const cssOutput = Object.assign({}, config, {
|
|
|
78
77
|
after: {
|
|
79
78
|
test: [
|
|
80
79
|
{
|
|
81
|
-
folder:
|
|
80
|
+
folder: "styles/css",
|
|
82
81
|
method: (absoluteItemPath) => {
|
|
83
|
-
return new RegExp(/\.js$/,
|
|
82
|
+
return new RegExp(/\.js$/, "m").test(absoluteItemPath);
|
|
84
83
|
},
|
|
85
|
-
}
|
|
86
|
-
]
|
|
87
|
-
}
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
},
|
|
88
87
|
}),
|
|
89
88
|
],
|
|
90
89
|
});
|
|
91
90
|
|
|
92
91
|
const jsDemoOutput = Object.assign({}, config, {
|
|
93
|
-
entry: [
|
|
92
|
+
entry: ["./example/App.jsx"],
|
|
94
93
|
output: {
|
|
95
|
-
path: path.resolve(__dirname,
|
|
96
|
-
filename:
|
|
94
|
+
path: path.resolve(__dirname, "demo"),
|
|
95
|
+
filename: "demo.mini.js",
|
|
97
96
|
},
|
|
98
97
|
resolve: {
|
|
99
98
|
alias: {
|
|
100
|
-
src: path.resolve(__dirname,
|
|
99
|
+
src: path.resolve(__dirname, "src/"),
|
|
101
100
|
},
|
|
102
|
-
extensions: [
|
|
101
|
+
extensions: [".js", ".jsx"],
|
|
103
102
|
},
|
|
104
103
|
module: {
|
|
105
104
|
rules: [
|
|
106
105
|
{
|
|
107
|
-
test: /\.js$/,
|
|
108
|
-
loader:
|
|
109
|
-
}
|
|
110
|
-
]
|
|
106
|
+
test: /\.(js|jsx)$/,
|
|
107
|
+
loader: "babel-loader",
|
|
108
|
+
},
|
|
109
|
+
],
|
|
111
110
|
},
|
|
112
111
|
plugins: [
|
|
113
112
|
new RemovePlugin({
|
|
@@ -117,21 +116,21 @@ const jsDemoOutput = Object.assign({}, config, {
|
|
|
117
116
|
after: {
|
|
118
117
|
test: [
|
|
119
118
|
{
|
|
120
|
-
folder:
|
|
119
|
+
folder: "demo",
|
|
121
120
|
method: (absoluteItemPath) => {
|
|
122
121
|
return new RegExp(/\.txt$/).test(absoluteItemPath);
|
|
123
122
|
},
|
|
124
|
-
}
|
|
125
|
-
]
|
|
126
|
-
}
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
},
|
|
127
126
|
}),
|
|
128
127
|
],
|
|
129
128
|
});
|
|
130
129
|
|
|
131
130
|
const cssDemoOutput = Object.assign({}, config, {
|
|
132
|
-
entry: [
|
|
131
|
+
entry: ["./styles/scss/image-gallery.scss", "./example/App.css"],
|
|
133
132
|
output: {
|
|
134
|
-
path: path.resolve(__dirname,
|
|
133
|
+
path: path.resolve(__dirname, "demo"),
|
|
135
134
|
},
|
|
136
135
|
module: {
|
|
137
136
|
rules: [
|
|
@@ -140,16 +139,16 @@ const cssDemoOutput = Object.assign({}, config, {
|
|
|
140
139
|
use: [
|
|
141
140
|
MiniCssExtractPlugin.loader,
|
|
142
141
|
// Translates CSS into CommonJS
|
|
143
|
-
|
|
142
|
+
"css-loader",
|
|
144
143
|
// Compiles Sass to CSS
|
|
145
|
-
|
|
144
|
+
"sass-loader",
|
|
146
145
|
],
|
|
147
|
-
}
|
|
148
|
-
]
|
|
146
|
+
},
|
|
147
|
+
],
|
|
149
148
|
},
|
|
150
149
|
plugins: [
|
|
151
150
|
new MiniCssExtractPlugin({
|
|
152
|
-
filename:
|
|
151
|
+
filename: "demo.mini.css",
|
|
153
152
|
}),
|
|
154
153
|
new RemovePlugin({
|
|
155
154
|
/**
|
|
@@ -158,13 +157,13 @@ const cssDemoOutput = Object.assign({}, config, {
|
|
|
158
157
|
after: {
|
|
159
158
|
test: [
|
|
160
159
|
{
|
|
161
|
-
folder:
|
|
160
|
+
folder: "demo",
|
|
162
161
|
method: (absoluteItemPath) => {
|
|
163
162
|
return new RegExp(/\.js$/).test(absoluteItemPath);
|
|
164
163
|
},
|
|
165
|
-
}
|
|
166
|
-
]
|
|
167
|
-
}
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
},
|
|
168
167
|
}),
|
|
169
168
|
],
|
|
170
169
|
});
|