react-image-gallery 1.3.0 → 2.0.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/LICENSE +1 -1
- package/README.md +80 -18
- package/build/image-gallery.cjs +1 -0
- package/build/image-gallery.css +1 -0
- package/build/image-gallery.es.js +1 -0
- package/build/types/types.d.ts +406 -0
- package/package.json +81 -47
- package/styles/image-gallery.css +683 -0
- package/.eslintrc.json +0 -47
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -39
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- package/.github/workflows/eslint.yml +0 -56
- package/babel.config.js +0 -3
- package/build/image-gallery.js +0 -1
- package/jest.config.js +0 -16
- package/src/components/ImageGallery.jsx +0 -1727
- package/src/components/ImageGallery.test.jsx +0 -22
- package/src/components/Item.jsx +0 -75
- package/src/components/SVG.jsx +0 -59
- package/src/components/SwipeWrapper.jsx +0 -37
- package/src/components/controls/Fullscreen.jsx +0 -25
- package/src/components/controls/LeftNav.jsx +0 -26
- package/src/components/controls/PlayPause.jsx +0 -25
- package/src/components/controls/RightNav.jsx +0 -26
- package/styles/css/image-gallery.css +0 -1
- package/styles/scss/image-gallery.scss +0 -453
- package/webpack.build.js +0 -171
- package/webpack.config.js +0 -52
|
@@ -1,22 +0,0 @@
|
|
|
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
|
-
});
|
package/src/components/Item.jsx
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
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;
|
package/src/components/SVG.jsx
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { number, oneOf, string } from "prop-types";
|
|
3
|
-
|
|
4
|
-
const left = <polyline points="15 18 9 12 15 6" />;
|
|
5
|
-
const right = <polyline points="9 18 15 12 9 6" />;
|
|
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
|
-
);
|
|
12
|
-
const play = <polygon points="5 3 19 12 5 21 5 3" />;
|
|
13
|
-
const pause = (
|
|
14
|
-
<React.Fragment>
|
|
15
|
-
<rect x="6" y="4" width="4" height="16" />
|
|
16
|
-
<rect x="14" y="4" width="4" height="16" />
|
|
17
|
-
</React.Fragment>
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
const iconMapper = {
|
|
21
|
-
left,
|
|
22
|
-
right,
|
|
23
|
-
maximize,
|
|
24
|
-
minimize,
|
|
25
|
-
play,
|
|
26
|
-
pause,
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const defaultProps = {
|
|
30
|
-
strokeWidth: 1,
|
|
31
|
-
viewBox: "0 0 24 24",
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const SVG = (props) => {
|
|
35
|
-
const { strokeWidth, viewBox, icon } = { ...defaultProps, ...props };
|
|
36
|
-
return (
|
|
37
|
-
<svg
|
|
38
|
-
className="image-gallery-svg"
|
|
39
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
40
|
-
viewBox={viewBox}
|
|
41
|
-
fill="none"
|
|
42
|
-
stroke="currentColor"
|
|
43
|
-
strokeWidth={strokeWidth}
|
|
44
|
-
strokeLinecap="round"
|
|
45
|
-
strokeLinejoin="round"
|
|
46
|
-
>
|
|
47
|
-
{iconMapper[icon]}
|
|
48
|
-
</svg>
|
|
49
|
-
);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
SVG.propTypes = {
|
|
53
|
-
strokeWidth: number,
|
|
54
|
-
viewBox: string,
|
|
55
|
-
icon: oneOf(["left", "right", "maximize", "minimize", "play", "pause"])
|
|
56
|
-
.isRequired,
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export default SVG;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { string, node, number, func } from "prop-types";
|
|
3
|
-
import { useSwipeable } from "react-swipeable";
|
|
4
|
-
|
|
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
|
-
const swipeHandlers = useSwipeable({
|
|
18
|
-
delta,
|
|
19
|
-
onSwiping,
|
|
20
|
-
onSwiped,
|
|
21
|
-
});
|
|
22
|
-
return (
|
|
23
|
-
<div {...swipeHandlers} className={className}>
|
|
24
|
-
{children}
|
|
25
|
-
</div>
|
|
26
|
-
);
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
SwipeWrapper.propTypes = {
|
|
30
|
-
children: node.isRequired,
|
|
31
|
-
className: string,
|
|
32
|
-
delta: number,
|
|
33
|
-
onSwiped: func,
|
|
34
|
-
onSwiping: func,
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export default SwipeWrapper;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { bool, func } from "prop-types";
|
|
3
|
-
import SVG from "src/components/SVG";
|
|
4
|
-
|
|
5
|
-
const Fullscreen = React.memo(({ isFullscreen, onClick }) => {
|
|
6
|
-
return (
|
|
7
|
-
<button
|
|
8
|
-
type="button"
|
|
9
|
-
className="image-gallery-icon image-gallery-fullscreen-button"
|
|
10
|
-
onClick={onClick}
|
|
11
|
-
aria-label="Open Fullscreen"
|
|
12
|
-
>
|
|
13
|
-
<SVG strokeWidth={2} icon={isFullscreen ? "minimize" : "maximize"} />
|
|
14
|
-
</button>
|
|
15
|
-
);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
Fullscreen.displayName = "Fullscreen";
|
|
19
|
-
|
|
20
|
-
Fullscreen.propTypes = {
|
|
21
|
-
isFullscreen: bool.isRequired,
|
|
22
|
-
onClick: func.isRequired,
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export default Fullscreen;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { bool, func } from "prop-types";
|
|
3
|
-
import SVG from "src/components/SVG";
|
|
4
|
-
|
|
5
|
-
const LeftNav = React.memo(({ disabled, onClick }) => {
|
|
6
|
-
return (
|
|
7
|
-
<button
|
|
8
|
-
type="button"
|
|
9
|
-
className="image-gallery-icon image-gallery-left-nav"
|
|
10
|
-
disabled={disabled}
|
|
11
|
-
onClick={onClick}
|
|
12
|
-
aria-label="Previous Slide"
|
|
13
|
-
>
|
|
14
|
-
<SVG icon="left" viewBox="6 0 12 24" />
|
|
15
|
-
</button>
|
|
16
|
-
);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
LeftNav.displayName = "LeftNav";
|
|
20
|
-
|
|
21
|
-
LeftNav.propTypes = {
|
|
22
|
-
disabled: bool.isRequired,
|
|
23
|
-
onClick: func.isRequired,
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export default LeftNav;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { bool, func } from "prop-types";
|
|
3
|
-
import SVG from "src/components/SVG";
|
|
4
|
-
|
|
5
|
-
const PlayPause = React.memo(({ isPlaying, onClick }) => {
|
|
6
|
-
return (
|
|
7
|
-
<button
|
|
8
|
-
type="button"
|
|
9
|
-
className="image-gallery-icon image-gallery-play-button"
|
|
10
|
-
onClick={onClick}
|
|
11
|
-
aria-label="Play or Pause Slideshow"
|
|
12
|
-
>
|
|
13
|
-
<SVG strokeWidth={2} icon={isPlaying ? "pause" : "play"} />
|
|
14
|
-
</button>
|
|
15
|
-
);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
PlayPause.displayName = "PlayPause";
|
|
19
|
-
|
|
20
|
-
PlayPause.propTypes = {
|
|
21
|
-
isPlaying: bool.isRequired,
|
|
22
|
-
onClick: func.isRequired,
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export default PlayPause;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { bool, func } from "prop-types";
|
|
3
|
-
import SVG from "src/components/SVG";
|
|
4
|
-
|
|
5
|
-
const RightNav = React.memo(({ disabled, onClick }) => {
|
|
6
|
-
return (
|
|
7
|
-
<button
|
|
8
|
-
type="button"
|
|
9
|
-
className="image-gallery-icon image-gallery-right-nav"
|
|
10
|
-
disabled={disabled}
|
|
11
|
-
onClick={onClick}
|
|
12
|
-
aria-label="Next Slide"
|
|
13
|
-
>
|
|
14
|
-
<SVG icon="right" viewBox="6 0 12 24" />
|
|
15
|
-
</button>
|
|
16
|
-
);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
RightNav.displayName = "RightNav";
|
|
20
|
-
|
|
21
|
-
RightNav.propTypes = {
|
|
22
|
-
disabled: bool.isRequired,
|
|
23
|
-
onClick: func.isRequired,
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export default RightNav;
|
|
@@ -1 +0,0 @@
|
|
|
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}}
|