react-three-d
Version:
A versatile React library designed to simplify the process of creating and manipulating 3D shapes using CSS.
197 lines • 11.6 kB
JavaScript
"use strict";
'use client';
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var react_1 = tslib_1.__importStar(require("react"));
function getUnit(unit) {
var _a;
return ((_a = unit.match(/^(\d+)(\D+)$/)) === null || _a === void 0 ? void 0 : _a.slice(1)) || [];
}
function getTransform(params) {
var theta = 360 / params.count;
var angle = theta * params.index * -1;
var fn = params.isHorizontal ? 'rotateY' : 'rotateX';
var size = getUnit(params.isHorizontal ? params.width : params.height)[0];
var radius = Math.round(+size / 2 / Math.tan(Math.PI / params.count));
return "translateZ(".concat(-radius, "px) ").concat(fn, "(").concat(angle, "deg)");
}
function useResizeObserver(ref) {
var _a = (0, react_1.useState)([0, 0]), dimensions = _a[0], setDimensions = _a[1];
(0, react_1.useEffect)(function () {
var targetElement = (ref === null || ref === void 0 ? void 0 : ref.current) || document.body;
var resizeObserver = new ResizeObserver(function (_a) {
var entry = _a[0];
setDimensions([entry.contentRect.width, entry.contentRect.height]);
});
resizeObserver.observe(targetElement);
return function () {
resizeObserver.unobserve(targetElement);
};
}, [ref]);
return dimensions;
}
function Gallery(_a) {
var children = _a.children, _b = _a.isInfiniteMode, isInfiniteMode = _b === void 0 ? false : _b, _c = _a.isNavigation, isNavigation = _c === void 0 ? true : _c, _d = _a.itemsToScroll, itemsToScroll = _d === void 0 ? 1 : _d, mouseSwipeRatio = _a.mouseSwipeRatio, mouseSwipeTreshold = _a.mouseSwipeTreshold, onChange = _a.onChange, _e = _a.responsiveProps, responsiveProps = _e === void 0 ? [] : _e, _f = _a.selectedIndex, selectedIndex = _f === void 0 ? 0 : _f, _g = _a.selectedProps, _h = _g === void 0 ? {} : _g, selectedCellClassName = _h.className, selectedProps = tslib_1.__rest(_h, ["className"]), _j = _a.swipeRatio, swipeRatio = _j === void 0 ? 1 : _j, swipeTreshold = _a.swipeTreshold, touchSwipeRatio = _a.touchSwipeRatio, touchSwipeTreshold = _a.touchSwipeTreshold, props = tslib_1.__rest(_a, ["children", "isInfiniteMode", "isNavigation", "itemsToScroll", "mouseSwipeRatio", "mouseSwipeTreshold", "onChange", "responsiveProps", "selectedIndex", "selectedProps", "swipeRatio", "swipeTreshold", "touchSwipeRatio", "touchSwipeTreshold"]);
var items = react_1.Children.toArray(children);
var count = react_1.Children.count(children);
var lastIndex = count - 1;
var sceneRef = (0, react_1.useRef)(null);
var carouselRef = (0, react_1.useRef)(null);
var isDraggingRef = (0, react_1.useRef)(false);
var dragStartPosRef = (0, react_1.useRef)(0);
var windowWidth = useResizeObserver()[0];
var propsByWindowWidth = responsiveProps.reduce(function (result, _a) {
if (_a === void 0) { _a = {}; }
var _b = _a.minWidth, minWidth = _b === void 0 ? 0 : _b, _c = _a.maxWidth, maxWidth = _c === void 0 ? null : _c, item = tslib_1.__rest(_a, ["minWidth", "maxWidth"]);
return windowWidth >= minWidth && (!maxWidth || windowWidth < maxWidth) ? tslib_1.__assign(tslib_1.__assign({}, result), item) : result;
}, props);
var _k = windowWidth ? propsByWindowWidth : props, height = _k.height, _l = _k.isHorizontal, isHorizontal = _l === void 0 ? true : _l, perspective = _k.perspective, style = _k.style, width = _k.width, restProps = tslib_1.__rest(_k, ["height", "isHorizontal", "perspective", "style", "width"]);
var getNextSlideIndex = (0, react_1.useCallback)(function (direction) {
if (direction === 'forward') {
var nextIndex = selectedIndex + itemsToScroll;
var isOnEnd = nextIndex > lastIndex;
var newSlideIndex = isOnEnd ? (isInfiniteMode ? nextIndex - lastIndex - 1 : lastIndex) : nextIndex;
return newSlideIndex;
}
if (direction === 'backward') {
var nextIndex = selectedIndex - itemsToScroll;
var isOnStart = nextIndex < 0;
var newSlideIndex = isOnStart ? (isInfiniteMode ? lastIndex + 1 + nextIndex : 0) : nextIndex;
return newSlideIndex;
}
return selectedIndex;
}, [selectedIndex, itemsToScroll, lastIndex, isInfiniteMode]);
var updateActiveSlideIndex = (0, react_1.useCallback)(function (newIndex) {
if (newIndex !== selectedIndex) {
var newTransform = getTransform({
count: count,
index: newIndex,
isHorizontal: isHorizontal,
width: width,
height: height,
});
carouselRef.current.style.transform = newTransform;
}
if (onChange) {
onChange(newIndex);
}
}, [selectedIndex, onChange, count, isHorizontal, width, height]);
(0, react_1.useEffect)(function () {
var element = carouselRef.current;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function handleSwipe(_event) {
isDraggingRef.current = true;
}
function handleSwipeEnd(event) {
var _a;
document.removeEventListener('mousemove', handleSwipe);
document.removeEventListener('mouseup', handleSwipeEnd);
document.removeEventListener('touchmove', handleSwipe);
document.removeEventListener('touchend', handleSwipeEnd);
if (isDraggingRef.current) {
var isTouch = !!((_a = event.changedTouches) === null || _a === void 0 ? void 0 : _a[0]);
var dragPos = isTouch
? event.changedTouches[event.changedTouches.length - 1].clientX
: event.clientX;
var mousePosDiff = (dragStartPosRef.current - dragPos) * ((isTouch ? touchSwipeRatio : mouseSwipeRatio) || swipeRatio);
var quarter = +getUnit(isHorizontal ? width : height)[0] / 4;
var treshold = (isTouch ? touchSwipeTreshold : mouseSwipeTreshold) || swipeTreshold || quarter;
var nextActiveSlide = mousePosDiff > treshold
? {
index: getNextSlideIndex('forward'),
direction: 'forward',
}
: mousePosDiff < -treshold
? {
index: getNextSlideIndex('backward'),
direction: 'backward',
}
: {
index: selectedIndex,
direction: 'forward',
};
updateActiveSlideIndex(nextActiveSlide.index);
}
dragStartPosRef.current = 0;
isDraggingRef.current = false;
}
function handleSwipeStart(event) {
var _a, _b;
var isTouch = !!((_a = event.touches) === null || _a === void 0 ? void 0 : _a[0]);
dragStartPosRef.current = isTouch ? (_b = event.touches) === null || _b === void 0 ? void 0 : _b[0].clientX : event.clientX;
if (isTouch) {
document.addEventListener('touchmove', handleSwipe);
document.addEventListener('touchend', handleSwipeEnd);
}
else {
document.addEventListener('mousemove', handleSwipe);
document.addEventListener('mouseup', handleSwipeEnd);
}
}
if (isNavigation) {
element === null || element === void 0 ? void 0 : element.addEventListener('touchstart', handleSwipeStart, { passive: true });
element === null || element === void 0 ? void 0 : element.addEventListener('mousedown', handleSwipeStart);
element === null || element === void 0 ? void 0 : element.addEventListener('dragstart', handleSwipeEnd);
}
return function () {
isDraggingRef.current = false;
dragStartPosRef.current = 0;
document.removeEventListener('mousemove', handleSwipe);
document.removeEventListener('mouseup', handleSwipeEnd);
document.removeEventListener('touchmove', handleSwipe);
document.removeEventListener('touchend', handleSwipeEnd);
element === null || element === void 0 ? void 0 : element.removeEventListener('touchstart', handleSwipeStart);
element === null || element === void 0 ? void 0 : element.removeEventListener('mousedown', handleSwipeStart);
element === null || element === void 0 ? void 0 : element.removeEventListener('dragstart', handleSwipeEnd);
};
}, [
getNextSlideIndex,
height,
isHorizontal,
isInfiniteMode,
isNavigation,
mouseSwipeRatio,
mouseSwipeTreshold,
selectedIndex,
swipeRatio,
swipeTreshold,
touchSwipeRatio,
touchSwipeTreshold,
updateActiveSlideIndex,
width,
]);
var carouselTransform = getTransform({
count: count,
index: selectedIndex,
isHorizontal: isHorizontal,
width: width,
height: height,
});
return (react_1.default.createElement("div", tslib_1.__assign({ style: tslib_1.__assign(tslib_1.__assign({}, style), { position: 'relative', width: width, height: height, perspective: perspective }), ref: sceneRef }, restProps),
react_1.default.createElement("div", { style: {
height: '100%',
position: 'absolute',
WebkitTransformStyle: 'preserve-3d',
MozTransformStyle: 'preserve-3d',
transformStyle: 'preserve-3d',
width: '100%',
WebkitTransition: '-webkit-transform 400ms ease-in-out',
MozTransition: '-moz-transform 400ms ease-in-out',
transition: 'transform 400ms ease-in-out',
WebkitTransform: carouselTransform,
transform: carouselTransform,
}, ref: carouselRef }, items.map(function (item, index, _a) {
var length = _a.length;
var _b = item.props, _c = _b === void 0 ? {} : _b, _d = _c.className, cellClassName = _d === void 0 ? '' : _d, _e = _c.style, cellStyle = _e === void 0 ? {} : _e, cellComponentProps = tslib_1.__rest(_c, ["className", "style"]), cellComponentData = tslib_1.__rest(item, ["props"]);
var isActive = index === selectedIndex;
var className = "".concat(cellClassName, " ").concat(isActive ? selectedCellClassName : '').trim() || undefined;
var _f = getUnit(isHorizontal ? width : height), value = _f[0], unit = _f[1];
var fn = isHorizontal ? 'rotateY' : 'rotateX';
var rotate = (360 / length) * index;
var translate = +value / 2 / Math.tan(Math.PI / length);
var cellProps = tslib_1.__assign(tslib_1.__assign({ role: 'cell', className: className, style: tslib_1.__assign(tslib_1.__assign({}, cellStyle), { height: '100%', left: '0', position: 'absolute', top: '0', width: '100%', WebkitTransform: "".concat(fn, "(").concat(rotate, "deg) translateZ(").concat(translate).concat(unit, ")"), transform: "".concat(fn, "(").concat(rotate, "deg) translateZ(").concat(translate).concat(unit, ")") }) }, cellComponentProps), (isActive ? selectedProps : {}));
return tslib_1.__assign({ props: cellProps }, cellComponentData);
}))));
}
exports.default = (0, react_1.memo)(Gallery);
//# sourceMappingURL=Gallery.js.map