UNPKG

lightswind

Version:

A collection of beautifully crafted React Components, Blocks & Templates for Modern Developers. Create stunning web applications effortlessly by using our 160+ professional and animated react components.

250 lines (242 loc) 10.4 kB
"use strict"; 'use client'; Object.defineProperty(exports, "__esModule", { value: true }); exports.ThreeDImageCarousel = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const lucide_react_1 = require("lucide-react"); const react_1 = require("react"); // --- MINIMIZED CSS Styles (Only core 3D positioning and responsiveness remain) --- const EMBEDDED_CSS = ` /* --- Cascade Slider Styles --- */ .cascade-slider_container { position: relative; max-width: 1000px; height: 40vh; margin: 0 auto; z-index: 20; user-select: none; -webkit-user-select: none; touch-action: pan-y; } .cascade-slider_slides { position: relative; height: 100%; } .cascade-slider_item { position: absolute; top: 50%; left: 50%; transform: translateY(-50%) translateX(-50%) scale(0.3); transition: all 1s ease; opacity: 0; z-index: 1; cursor: grab; } .cascade-slider_item.now { cursor: default; } .cascade-slider_item:active { cursor: grabbing; } /* Slide Positioning Classes (Core 3D Logic - MUST REMAIN IN CSS) */ .cascade-slider_item.next { left: 50%; transform: translateY(-50%) translateX(-120%) scale(0.6); opacity: 1; z-index: 4; } .cascade-slider_item.prev { left: 50%; transform: translateY(-50%) translateX(20%) scale(0.6); opacity: 1; z-index: 4; } .cascade-slider_item.now { top: 50%; left: 50%; transform: translateY(-50%) translateX(-50%) scale(1); opacity: 1; z-index: 5; } /* Arrows - Structural CSS remains for positioning/size */ .cascade-slider_arrow { display: flex; align-items: center; justify-content: center; position: absolute; top: 50%; cursor: pointer; z-index: 6; transform: translate(0, -50%); width: 40px; height: 40px; transition: all 0.3s ease; /* Tailwind will handle color/bg */ } /* Arrow Positioning Fix (Responsive CSS) */ @media screen and (max-width: 575px) { .cascade-slider_arrow-left { left: 5px; } .cascade-slider_arrow-right { right: 5px; } } @media screen and (min-width: 576px) { .cascade-slider_arrow-left { left: -4%; } .cascade-slider_arrow-right { right: -4%; } } /* Images */ .cascade-slider_slides img { max-width: 150px; height: auto; border-radius: 35px; display: block; transition: filter 1s ease; } /* Tailwind handles the grayscale filter on hover if desired, but keeping the state-based one is better */ .cascade-slider_item:not(.now) img { filter: grayscale(0.95); } /* --- Media Queries (Minimized to only include structural layout changes) --- */ @media screen and (min-width: 414px) { .cascade-slider_container { height: 50vh; } .cascade-slider_slides img { max-width: 200px; } } @media screen and (min-width: 576px) { .cascade-slider_container { height: 60vh; } .cascade-slider_slides img { max-width: 270px; } } @media screen and (min-width: 768px) { .cascade-slider_item.next { transform: translateY(-50%) translateX(-125%) scale(0.6); } .cascade-slider_item.prev { transform: translateY(-50%) translateX(25%) scale(0.6); } .cascade-slider_slides img { max-width: 250px; } } @media screen and (min-width: 991px) { .cascade-slider_item.next { transform: translateY(-50%) translateX(-115%) scale(0.55); z-index: 4; } .cascade-slider_item.prev { transform: translateY(-50%) translateX(15%) scale(0.55); z-index: 4; } .cascade-slider_item.next2 { transform: translateY(-50%) translateX(-150%) scale(0.37); z-index: 1; } .cascade-slider_item.prev2 { transform: translateY(-50%) translateX(50%) scale(0.37); z-index: 2; } .cascade-slider_slides img { max-width: 300px; } .cascade-slider_container { height: 67vh; } } @media screen and (min-width: 1100px) { .cascade-slider_item.next { transform: translateY(-50%) translateX(-130%) scale(0.55); } .cascade-slider_item.prev { transform: translateY(-50%) translateX(30%) scale(0.55); } .cascade-slider_item.next2 { transform: translateY(-50%) translateX(-180%) scale(0.37); } .cascade-slider_item.prev2 { transform: translateY(-50%) translateX(80%) scale(0.37); } .cascade-slider_slides img { max-width: 350px; } } `; // --- Helper Function: Get Slide Classes --- const getSlideClasses = (index, activeIndex, total, visibleCount) => { const diff = index - activeIndex; if (diff === 0) return 'now'; if (diff === 1 || diff === -total + 1) return 'next'; if (visibleCount === 5 && (diff === 2 || diff === -total + 2)) return 'next2'; if (diff === -1 || diff === total - 1) return 'prev'; if (visibleCount === 5 && (diff === -2 || diff === total - 2)) return 'prev2'; return ''; }; // --- ThreeDImageCarousel Component Logic --- const ThreeDImageCarousel = ({ slides, itemCount = 5, autoplay = false, delay = 3, pauseOnHover = true, className = '', }) => { const [activeIndex, setActiveIndex] = (0, react_1.useState)(0); const autoplayIntervalRef = (0, react_1.useRef)(null); const total = slides.length; const [isDragging, setIsDragging] = (0, react_1.useState)(false); const [startX, setStartX] = (0, react_1.useState)(0); const swipeThreshold = 50; const navigate = (0, react_1.useCallback)((direction) => { setActiveIndex(current => { if (direction === 'next') { return (current + 1) % total; } else { return (current - 1 + total) % total; } }); }, [total]); const startAutoplay = (0, react_1.useCallback)(() => { if (autoplay && total > 1) { if (autoplayIntervalRef.current) { clearInterval(autoplayIntervalRef.current); } autoplayIntervalRef.current = window.setInterval(() => { navigate('next'); }, delay * 1000); } }, [autoplay, delay, navigate, total]); const stopAutoplay = (0, react_1.useCallback)(() => { if (autoplayIntervalRef.current) { clearInterval(autoplayIntervalRef.current); autoplayIntervalRef.current = null; } }, []); (0, react_1.useEffect)(() => { startAutoplay(); return () => { stopAutoplay(); }; }, [startAutoplay, stopAutoplay]); // Handler to stop autoplay on hover const handleMouseEnter = () => { if (autoplay && pauseOnHover) { stopAutoplay(); } }; // Handler to start autoplay on mouse exit AND handle drag cancellation const handleExit = (e) => { // 1. Autoplay resume logic if (autoplay && pauseOnHover) { startAutoplay(); } // 2. Drag cancellation logic (Equivalent to the removed onMouseLeaveDrag) if (isDragging) { handleEnd(e.clientX); } }; // --- Touch/Mouse Drag Logic --- const handleStart = (clientX) => { setIsDragging(true); setStartX(clientX); stopAutoplay(); }; const handleEnd = (clientX) => { if (!isDragging) return; const distance = clientX - startX; if (Math.abs(distance) > swipeThreshold) { if (distance < 0) { navigate('next'); // Swipe left (negative distance) -> show next slide } else { navigate('prev'); // Swipe right (positive distance) -> show previous slide } } setIsDragging(false); setStartX(0); // Autoplay is resumed by the useEffect on state change or by handleExit/onMouseUp }; const onMouseDown = (e) => handleStart(e.clientX); const onMouseUp = (e) => { handleEnd(e.clientX); startAutoplay(); // Resume autoplay when mouse button is released }; const onTouchStart = (e) => handleStart(e.touches[0].clientX); const onTouchEnd = (e) => { handleEnd(e.changedTouches[0].clientX); startAutoplay(); // Resume autoplay after touch interaction }; return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("style", { dangerouslySetInnerHTML: { __html: EMBEDDED_CSS } }), (0, jsx_runtime_1.jsxs)("div", { className: `cascade-slider_container ${className} bg-transparent`, onMouseEnter: handleMouseEnter, onMouseLeave: handleExit, onMouseDown: onMouseDown, onMouseUp: onMouseUp, onTouchStart: onTouchStart, onTouchEnd: onTouchEnd, children: [(0, jsx_runtime_1.jsx)("div", { className: "cascade-slider_slides", children: slides.map((slide, index) => ((0, jsx_runtime_1.jsx)("div", { className: `cascade-slider_item ${getSlideClasses(index, activeIndex, total, itemCount)}`, "data-slide-number": index, children: (0, jsx_runtime_1.jsx)("a", { href: slide.href, children: (0, jsx_runtime_1.jsx)("img", { src: slide.src, alt: `Slide ${index + 1}`, // Fallback for image loading onError: (e) => { e.currentTarget.onerror = null; e.currentTarget.src = `https://placehold.co/350x200/4F46E5/ffffff?text=Slide%20${index + 1}`; } }) }) }, slide.id))) }), total > 1 && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: "cascade-slider_arrow cascade-slider_arrow-left rounded-full bg-black/30 text-white p-2 hover:bg-black/60 transition-colors duration-300", onClick: (e) => { e.stopPropagation(); navigate('prev'); }, "data-action": "prev", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ArrowLeftCircle, { size: 30 }) }), (0, jsx_runtime_1.jsx)("span", { className: "cascade-slider_arrow cascade-slider_arrow-right rounded-full bg-black/30 text-white p-2 hover:bg-black/60 transition-colors duration-300", onClick: (e) => { e.stopPropagation(); navigate('next'); }, "data-action": "next", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ArrowRightCircle, { size: 30 }) })] }))] })] })); }; exports.ThreeDImageCarousel = ThreeDImageCarousel; exports.default = exports.ThreeDImageCarousel; //# sourceMappingURL=ThreeDImageCarousel.js.map