gatsby-image-background-slider
Version:
Lazy-loaded background images, with a simple fade transition between them, using gatsby-image. Inspired by react-background-slider, except for—well—the obvious.
339 lines (284 loc) • 9.3 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var React = require('react');
var React__default = _interopDefault(React);
var PropTypes = _interopDefault(require('prop-types'));
var Img = _interopDefault(require('gatsby-image'));
var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
var objectWithoutProperties = function (obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
};
var slicedToArray = function () {
function sliceIterator(arr, i) {
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"]) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
return function (arr, i) {
if (Array.isArray(arr)) {
return arr;
} else if (Symbol.iterator in Object(arr)) {
return sliceIterator(arr, i);
} else {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
};
}();
/**
* @param {object} props Component props
* @param {object} props.callbacks interface for callback functions (pass this to Pagination, if used)
* @param {(newIndex:number) => void} props.callbacks.atIndex sets background to specified index
* @param {(prevIndex: number, newIndex: number) => void} props.callbacks.onChange user-provided callback fired when background image changes
* @param {Function} props.callbacks.next sets background to the next one
* @param {Function} props.callbacks.prev sets background to the previous one
* @param {string[]} props.images list of specified image file names to set order
* @param {number} [props.duration=5] duration background is shown for
* @param {number} [props.transition=2] length of transition
* @param {object.isRequired} props.query result of GraphQL query for images
* @param {JSXElement[]} props.children subtitles/captions in sync for respective background images;
* (<React.Fragment/> to skip over one)
* @param {Array} props.gatsbyImageProps remaining props spread onto Img elements
* @param {number} [props.initDelay=5] initial delay before first transition
*/
var BackgroundSlider = function BackgroundSlider(_ref) {
var callbacks = _ref.callbacks,
images = _ref.images,
duration = _ref.duration,
transition = _ref.transition,
initDelay = _ref.initDelay,
query = _ref.query,
children = _ref.children,
gatsbyImageProps = objectWithoutProperties(_ref, ['callbacks', 'images', 'duration', 'transition', 'initDelay', 'query', 'children']);
var nodes = [];
var bgRefs = [];
var subRefs = [];
var bgWrappers = [];
var subWrappers = [];
var style = gatsbyImageProps.style,
imageProps = objectWithoutProperties(gatsbyImageProps, ['style']);
nodes.safePush = function (data) {
if (data) {
return this.push(data);
} else {
return this.length;
}
};
if (images) {
var _loop = function _loop(image) {
nodes.safePush(query.backgrounds.nodes.find(function (node) {
return node.relativePath === image;
}));
};
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = images[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var image = _step.value;
_loop(image);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
} else {
nodes = query.backgrounds.nodes;
}
var imgs = nodes.map(function (data, index) {
var backgroundStyle = {
position: "absolute",
zIndex: -10,
width: "100%",
height: "100%",
margin: 0,
padding: "none",
left: 0, top: 0,
backgroundSize: "cover",
opacity: index ? 0 : 1,
transition: 'opacity ' + transition + 's'
};
var subStyle = {
opacity: index ? 0 : 1,
transition: 'opacity ' + transition + 's',
pointerEvents: index ? "none" : "auto"
};
subRefs[index] = React__default.createRef();
bgRefs[index] = React__default.createRef();
return React__default.createElement(
React__default.Fragment,
{ key: index },
React__default.createElement(
'div',
{ ref: bgRefs[index] },
React__default.createElement(Img, _extends({ fluid: data.childImageSharp.fluid, style: _extends({}, backgroundStyle, style) }, imageProps))
),
React__default.createElement(
'div',
{ ref: subRefs[index], style: subStyle },
React__default.Children.toArray(children)[index]
)
);
});
var _useState = React.useState(0),
_useState2 = slicedToArray(_useState, 2),
timeoutHandle = _useState2[0],
setTimeoutHandle = _useState2[1];
var timeoutHandleRef = React.useRef(timeoutHandle);
timeoutHandleRef.current = timeoutHandle;
var _useState3 = React.useState(0),
_useState4 = slicedToArray(_useState3, 2),
index = _useState4[0],
setIndex = _useState4[1];
var indexRef = React.useRef(index);
indexRef.current = index;
if (callbacks) callbacks.getCount = function () {
return imgs.length;
};
var clearAndSetTimeoutHandle = function clearAndSetTimeoutHandle(newTimeoutHandle) {
clearTimeout(timeoutHandleRef.current);
setTimeoutHandle(newTimeoutHandle);
};
var initEffect = function initEffect() {
bgRefs.forEach(function (bgRef) {
bgWrappers.push(bgRef.current.firstElementChild);
});
subRefs.forEach(function (subRef) {
subWrappers.push(subRef.current);
});
var length = bgWrappers.length;
var changeIndex = function changeIndex(newIndex) {
var index = indexRef.current;
clearTimeout(timeoutHandleRef.current);
bgWrappers[index].style.opacity = 0;
bgWrappers[newIndex % length].style.opacity = 1;
subWrappers[index].style.opacity = 0;
subWrappers[index].style.pointerEvents = "none";
subWrappers[newIndex % length].style.opacity = 1;
subWrappers[newIndex % length].style.pointerEvents = "auto";
if (callbacks && callbacks.onChange) {
callbacks.onChange(index, newIndex % length);
}
setIndex(newIndex % length);
clearAndSetTimeoutHandle(setTimeout(callback, duration * 1000));
};
var callback = function callback() {
var index = indexRef.current;
changeIndex(index + 1);
};
clearAndSetTimeoutHandle(setTimeout(callback, initDelay * 1000));
if (callbacks) {
callbacks.atIndex = changeIndex;
callbacks.next = function () {
return callbacks.atIndex((indexRef.current + 1) % length);
};
callbacks.prev = function () {
return callbacks.atIndex((indexRef.current + length - 1) % length);
};
}
return function () {
clearTimeout(timeoutHandleRef.current);
};
};
// Runs once after DOM is loaded; effectively `componentDidMount`
React.useEffect(initEffect, []);
return React__default.createElement(
React__default.Fragment,
null,
imgs
);
};
BackgroundSlider.defaultProps = {
images: null,
duration: 5,
transition: 2,
initDelay: 5
};
BackgroundSlider.propTypes = {
query: PropTypes.object.isRequired,
images: PropTypes.arrayOf(PropTypes.string),
duration: PropTypes.number,
transition: PropTypes.number,
initDelay: PropTypes.number
};
var Pagination = function Pagination(_ref2) {
var callbacks = _ref2.callbacks;
var buttonRefs = [];
React.useEffect(function () {
callbacks.onChange = function (prevIndex, newIndex) {
buttonRefs[prevIndex].current.style.color = 'silver';
buttonRefs[prevIndex].current.style.transform = 'scale(1.0,1.0)';
buttonRefs[newIndex].current.style.color = 'white';
buttonRefs[newIndex].current.style.transform = "scale(1.2, 1.2)";
};
}, []);
return React__default.createElement(
React__default.Fragment,
null,
Array.from(Array(callbacks.getCount()).keys()).map(function (index) {
return React__default.createElement(
'span',
{ role: 'button', ref: buttonRefs[index] = React__default.createRef(),
key: index,
style: {
userSelect: 'none',
color: index === 0 ? 'white' : 'silver',
fontSize: '4em',
cursor: 'pointer',
display: 'inline-block',
transform: index === 0 ? 'scale(1.2,1.2)' : 'scale(1.0)'
},
onClick: function onClick() {
return callbacks.atIndex(index);
} },
'\xB7'
);
})
);
};
exports.default = BackgroundSlider;
exports.Pagination = Pagination;
//# sourceMappingURL=index.js.map