react-round-carousel
Version:
An infinitely scrollable 3D carousel component for React
81 lines (80 loc) • 5.21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Carousel = void 0;
var tslib_1 = require("tslib");
var jsx_runtime_1 = require("react/jsx-runtime");
var touchsweep_1 = require("touchsweep");
var uuid_1 = require("uuid");
var react_1 = require("react");
exports.Carousel = (0, react_1.forwardRef)(function (_a, CarouselRef) {
var items = _a.items, _b = _a.itemWidth, itemWidth = _b === void 0 ? 210 : _b, _c = _a.showControls, showControls = _c === void 0 ? true : _c, _d = _a.slideOnClick, slideOnClick = _d === void 0 ? false : _d, _e = _a.classNamePrefix, classNamePrefix = _e === void 0 ? 'carousel' : _e, _f = _a.prevButtonContent, prevButtonContent = _f === void 0 ? 'Previous' : _f, _g = _a.nextButtonContent, nextButtonContent = _g === void 0 ? 'Next' : _g;
var data = (0, react_1.useMemo)(function () {
return items.map(function (item) { return (tslib_1.__assign(tslib_1.__assign({}, item), (item.id
? {}
: { id: (0, uuid_1.v4)() }))); });
}, [items]);
var len = (0, react_1.useMemo)(function () { return data.length; }, [data.length]);
var theta = (0, react_1.useMemo)(function () { return 360 / len; }, [len]);
var radius = (0, react_1.useMemo)(function () { return Math.round(itemWidth / 2 / Math.tan(Math.PI / len)); }, [itemWidth, len]);
var ref = (0, react_1.useRef)(null);
var _h = (0, react_1.useState)(0), selectedIndex = _h[0], setSelectedIndex = _h[1];
var getSlideStyle = (0, react_1.useCallback)(function (index) {
var style = {};
if (index < len) {
var cellAngle = theta * index;
style.opacity = 1;
style.transform = "rotateY(".concat(cellAngle, "deg) translateZ(").concat(radius, "px)");
}
else {
style.opacity = 0;
style.transform = 'none';
}
return style;
}, [len, radius, theta]);
var getItemStyle = (0, react_1.useCallback)(function () {
var angle = theta * selectedIndex * -1;
return {
transform: "translateZ(".concat(-1 * radius, "px) rotateY(").concat(angle, "deg)")
};
}, [radius, selectedIndex, theta]);
var getClassName = (0, react_1.useCallback)(function (parts) {
return Array.isArray(parts)
? parts
.map(function (part) { return "".concat(classNamePrefix).concat(part); })
.join(' ')
: "".concat(classNamePrefix).concat(parts);
}, [classNamePrefix]);
var prev = (0, react_1.useCallback)(function () { return setSelectedIndex(selectedIndex - 1); }, [selectedIndex]);
var next = (0, react_1.useCallback)(function () { return setSelectedIndex(selectedIndex + 1); }, [selectedIndex]);
(0, react_1.useEffect)(function () {
var area = ref === null || ref === void 0 ? void 0 : ref.current;
var touchsweep = new touchsweep_1.default(area !== null && area !== void 0 ? area : undefined);
area === null || area === void 0 ? void 0 : area.addEventListener('swipeleft', next);
area === null || area === void 0 ? void 0 : area.addEventListener('swiperight', prev);
return function () {
touchsweep.unbind();
area === null || area === void 0 ? void 0 : area.removeEventListener('swipeleft', next);
area === null || area === void 0 ? void 0 : area.removeEventListener('swiperight', prev);
};
});
(0, react_1.useImperativeHandle)(CarouselRef, function () { return ({
next: next,
prev: prev,
getItems: function () { return data; },
getSelectedIndex: function () { return selectedIndex; },
setSelectedIndex: function (index) { return setSelectedIndex(index); }
}); });
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: getClassName(''), ref: ref, children: (0, jsx_runtime_1.jsx)("div", { className: getClassName('__container'), style: getItemStyle(), children: data.map(function (item, index) { return ((0, jsx_runtime_1.jsxs)("div", { style: getSlideStyle(index), onClick: function () {
if (item.onClick)
item.onClick();
if (slideOnClick)
setSelectedIndex(index);
}, className: getClassName('__slide'), children: [(0, jsx_runtime_1.jsx)("img", { src: item.image, alt: item.alt }), (0, jsx_runtime_1.jsx)("div", { className: getClassName('__slide-overlay'), children: item.content })] }, item.id)); }) }) }), showControls && ((0, jsx_runtime_1.jsxs)("div", { className: getClassName('__controls'), children: [(0, jsx_runtime_1.jsx)("button", { className: getClassName([
'__control',
'__control--prev'
]), onClick: prev, children: prevButtonContent }), (0, jsx_runtime_1.jsx)("button", { className: getClassName([
'__control',
'__control--next'
]), onClick: next, children: nextButtonContent })] }))] }));
});
exports.default = exports.Carousel;