react-status-stories
Version:
A lightweight and customizable React component to display WhatsApp-style status stories with circular previews. Perfect for building Instagram, WhatsApp, or Snapchat-like story UIs in your React apps.
79 lines (78 loc) • 5 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState, useEffect, useRef } from "react";
var ReactStatus = function (_a) {
var items = _a.items, _b = _a.timeout, timeout = _b === void 0 ? 3000 : _b, _c = _a.customClass, customClass = _c === void 0 ? "" : _c;
var _d = useState(0), activeIndex = _d[0], setActiveIndex = _d[1];
var _e = useState(timeout), newTime = _e[0], setNewTime = _e[1];
var _f = useState(false), isPaused = _f[0], setIsPaused = _f[1];
var timerRef = useRef(null);
var mouseLeaveRef = useRef(null);
var timeCheck = Date.now();
// Setting active index
var handleTimeout = function () {
clearInterval(mouseLeaveRef.current);
clearInterval(timerRef.current);
};
var handleImage = function (e) {
handleTimeout();
setIsPaused(false);
setNewTime(timeout);
setActiveIndex(function (prevIndex) {
return e === "previous"
? (prevIndex + items.length - 1) % items.length
: (prevIndex + 1) % items.length;
});
};
// Incrementing index after timeout
var handleIncrementIndex = function () {
handleTimeout();
setActiveIndex(function (prevIndex) { return (prevIndex + 1) % items.length; });
setNewTime(timeout);
};
// Clearing timeout and calling increment index function
useEffect(function () {
if (!isPaused) {
timerRef.current = setInterval(handleIncrementIndex, timeout);
}
return function () { return clearInterval(timerRef.current); };
}, [activeIndex]);
// Pause Time
var handlePause = function () {
var currentTime = Date.now() - timeCheck;
setNewTime(newTime - currentTime);
setIsPaused(true);
handleTimeout();
};
// Play
var handlePlay = function () {
setIsPaused(false);
mouseLeaveRef.current = setInterval(handleIncrementIndex, newTime);
};
// Handling pause and play of time
var handleTimeElapsed = function (e) {
if (e.type === "touchstart") {
handlePause();
}
else if (e.type === "touchend") {
handlePlay();
}
};
return (_jsxs("div", { className: "jul-stories ".concat(customClass).replace(/\s\s+/g, " ").trim(), onTouchStart: function (e) { return handleTimeElapsed(e); }, onTouchEnd: function (e) { return handleTimeElapsed(e); }, children: [_jsx("div", { className: "jul-stories__container", children: _jsxs("figure", { children: [_jsx("img", { src: items[activeIndex].imageUrl, alt: "story" }), _jsx("figcaption", { children: items[activeIndex].imageCaption })] }) }), items.length !== 1 && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "jul-stories__control", children: [_jsx("button", { onClick: function () { return handleImage("previous"); }, children: "Previous" }), _jsx("button", { onClick: function () { return handleImage("next"); }, children: "Next" })] }), _jsx("div", { className: "jul-stories__progressContainer", children: items.map(function (i, index) {
return (_jsx("div", { className: "jul-stories__progressItems", children: _jsx("span", { className: "".concat(index === activeIndex
? "jul-stories__progressItems--active"
: ""), style: {
animationDuration: "".concat(timeout, "ms"),
animationPlayState: isPaused ? "paused" : "running",
} }) }, index));
}) }), _jsx("div", { className: "jul-stories__pause-play ".concat(isPaused
? "jul-stories__pause-play--paused"
: "jul-stories__pause-play--play"), role: "button", onClick: function (e) {
if (!isPaused) {
handlePause();
}
else {
handlePlay();
}
}, "aria-label": isPaused ? "play" : "pause", children: !isPaused ? (_jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "white", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("path", { d: "M10 4.93652H6V20.9365H10V4.93652Z", stroke: "#1c2433", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M14 20.9365V4.93652H18V20.9365H14Z", stroke: "#1c2433", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })] })) : (_jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "white", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M5 3.93652L19 12.9365L5 21.9365V3.93652Z", stroke: "#1c2433", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })) })] }))] }));
};
export default ReactStatus;