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.

197 lines 13.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ScrollTimeline = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); const framer_motion_1 = require("framer-motion"); const utils_1 = require("@/components/lib/utils"); const card_1 = require("./card"); const lucide_react_1 = require("lucide-react"); const DEFAULT_EVENTS = [ { year: "2023", title: "Major Achievement", subtitle: "Organization Name", description: "Description of the achievement or milestone reached during this time period.", }, { year: "2022", title: "Important Milestone", subtitle: "Organization Name", description: "Details about this significant milestone and its impact.", }, { year: "2021", title: "Key Event", subtitle: "Organization Name", description: "Information about this key event in the timeline.", }, ]; const ScrollTimeline = ({ events = DEFAULT_EVENTS, title = "Timeline", subtitle = "Scroll to explore the journey", animationOrder = "sequential", cardAlignment = "alternating", lineColor = "bg-primary/30", activeColor = "bg-primary", progressIndicator = true, cardVariant = "default", cardEffect = "none", parallaxIntensity = 0.2, progressLineWidth = 2, progressLineCap = "round", dateFormat = "badge", revealAnimation = "fade", className = "", connectorStyle = "line", perspective = false, darkMode = false, smoothScroll = true, }) => { const scrollRef = (0, react_1.useRef)(null); const [activeIndex, setActiveIndex] = (0, react_1.useState)(-1); const timelineRefs = (0, react_1.useRef)([]); const { scrollYProgress } = (0, framer_motion_1.useScroll)({ target: scrollRef, offset: ["start start", "end end"], }); const smoothProgress = (0, framer_motion_1.useSpring)(scrollYProgress, { stiffness: 100, damping: 30, restDelta: 0.001, }); const progressHeight = (0, framer_motion_1.useTransform)(smoothProgress, [0, 1], ["0%", "100%"]); (0, react_1.useEffect)(() => { const unsubscribe = scrollYProgress.onChange((v) => { const newIndex = Math.floor(v * events.length); if (newIndex !== activeIndex && newIndex >= 0 && newIndex < events.length) { setActiveIndex(newIndex); } }); return () => unsubscribe(); }, [scrollYProgress, events.length, activeIndex]); const getCardVariants = (index) => { const baseDelay = animationOrder === "simultaneous" ? 0 : animationOrder === "staggered" ? index * 0.2 : index * 0.3; const initialStates = { fade: { opacity: 0, y: 20 }, slide: { x: cardAlignment === "left" ? -100 : cardAlignment === "right" ? 100 : index % 2 === 0 ? -100 : 100, opacity: 0, }, scale: { scale: 0.8, opacity: 0 }, flip: { rotateY: 90, opacity: 0 }, none: { opacity: 1 }, }; return { initial: initialStates[revealAnimation], whileInView: { opacity: 1, y: 0, x: 0, scale: 1, rotateY: 0, transition: { duration: 0.7, delay: baseDelay, ease: [0.25, 0.1, 0.25, 1.0], }, }, viewport: { once: false, margin: "-100px" }, }; }; const getConnectorClasses = () => { const baseClasses = (0, utils_1.cn)("absolute left-1/2 transform -translate-x-1/2", lineColor); const widthStyle = `w-[${progressLineWidth}px]`; switch (connectorStyle) { case "dots": return (0, utils_1.cn)(baseClasses, "w-1 rounded-full"); case "dashed": return (0, utils_1.cn)(baseClasses, widthStyle, `[mask-image:linear-gradient(to_bottom,black_33%,transparent_33%,transparent_66%,black_66%)] [mask-size:1px_12px]`); case "line": default: return (0, utils_1.cn)(baseClasses, widthStyle); } }; const getCardClasses = (index) => { const baseClasses = "relative z-30 rounded-lg transition-all duration-300"; const variantClasses = { default: "bg-card border shadow-sm", elevated: "bg-card border border-border/40 shadow-md", outlined: "bg-card/50 backdrop-blur border-2 border-primary/20", filled: "bg-primary/10 border border-primary/30", }; const effectClasses = { none: "", glow: "hover:shadow-[0_0_15px_rgba(var(--primary-rgb)/0.5)]", shadow: "hover:shadow-lg hover:-translate-y-1", bounce: "hover:scale-[1.03] hover:shadow-md active:scale-[0.97]", }; const alignmentClassesDesktop = cardAlignment === "alternating" ? index % 2 === 0 ? "lg:mr-[calc(50%+20px)]" : "lg:ml-[calc(50%+20px)]" : cardAlignment === "left" ? "lg:mr-auto lg:ml-0" : "lg:ml-auto lg:mr-0"; const perspectiveClass = perspective ? "transform transition-transform hover:rotate-y-1 hover:rotate-x-1" : ""; return (0, utils_1.cn)(baseClasses, variantClasses[cardVariant], effectClasses[cardEffect], alignmentClassesDesktop, "w-full lg:w-[calc(50%-40px)]"); }; return ((0, jsx_runtime_1.jsxs)("div", { ref: scrollRef, className: (0, utils_1.cn)("relative min-h-screen w-full overflow-hidden", darkMode ? "bg-background text-foreground" : "", className), children: [(0, jsx_runtime_1.jsxs)("div", { className: "text-center py-16 px-4", children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-3xl md:text-5xl font-bold mb-4", children: title }), (0, jsx_runtime_1.jsx)("p", { className: "text-lg text-muted-foreground max-w-2xl mx-auto", children: subtitle })] }), (0, jsx_runtime_1.jsx)("div", { className: "relative max-w-6xl mx-auto px-4 pb-24", children: (0, jsx_runtime_1.jsxs)("div", { className: "relative mx-auto", children: [(0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)(getConnectorClasses(), "h-full absolute top-0 z-10") }), progressIndicator && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { className: "absolute top-0 z-10", style: { height: progressHeight, width: progressLineWidth, left: "50%", transform: "translateX(-50%)", borderRadius: progressLineCap === "round" ? "9999px" : "0px", background: `linear-gradient(to bottom, #22d3ee, #6366f1, #a855f7)`, // Enhanced shadow for a constant glow effect along the path boxShadow: ` 0 0 15px rgba(99,102,241,0.5), 0 0 25px rgba(168,85,247,0.3) `, } }), (0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { className: "absolute z-20", style: { top: progressHeight, left: "50%", translateX: "-50%", translateY: "-50%", // Center the comet on the line's end point }, children: (0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { className: "w-5 h-5 rounded-full" // Size of the comet core , style: { background: "radial-gradient(circle, rgba(168,85,247,0.8) 0%, rgba(99,102,241,0.5) 40%, rgba(34,211,238,0) 70%)", // Intense, layered glow effect for the comet boxShadow: ` 0 0 15px 4px rgba(168, 85, 247, 0.6), 0 0 25px 8px rgba(99, 102, 241, 0.4), 0 0 40px 15px rgba(34, 211, 238, 0.2) `, }, animate: { scale: [1, 1.3, 1], }, transition: { duration: 2, repeat: Infinity, ease: "easeInOut", } }) })] })), (0, jsx_runtime_1.jsx)("div", { className: "relative z-20", children: events.map((event, index) => { const yOffset = (0, framer_motion_1.useTransform)(smoothProgress, [0, 1], [parallaxIntensity * 100, -parallaxIntensity * 100]); return ((0, jsx_runtime_1.jsxs)("div", { ref: (el) => { timelineRefs.current[index] = el; }, className: (0, utils_1.cn)("relative flex items-center mb-20 py-4", "flex-col lg:flex-row", cardAlignment === "alternating" ? index % 2 === 0 ? "lg:justify-start" : "lg:flex-row-reverse lg:justify-start" : cardAlignment === "left" ? "lg:justify-start" : "lg:flex-row-reverse lg:justify-start"), children: [(0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("absolute top-1/2 transform -translate-y-1/2 z-30", "left-1/2 -translate-x-1/2"), children: (0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { className: (0, utils_1.cn)("w-6 h-6 rounded-full border-4 bg-background flex items-center justify-center", index <= activeIndex ? "border-primary" : "border bg-card"), animate: index <= activeIndex ? { scale: [1, 1.3, 1], boxShadow: [ "0 0 0px rgba(99,102,241,0)", "0 0 12px rgba(99,102,241,0.6)", "0 0 0px rgba(99,102,241,0)", ], } : {}, transition: { duration: 0.8, repeat: Infinity, repeatDelay: 4, ease: "easeInOut", } }) }), (0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { className: (0, utils_1.cn)(getCardClasses(index), "mt-12 lg:mt-0"), variants: getCardVariants(index), initial: "initial", whileInView: "whileInView", viewport: { once: false, margin: "-100px" }, style: parallaxIntensity > 0 ? { y: yOffset } : undefined, children: (0, jsx_runtime_1.jsx)(card_1.Card, { className: "bg-background border", children: (0, jsx_runtime_1.jsxs)(card_1.CardContent, { className: "p-6", children: [dateFormat === "badge" ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center mb-2", children: [event.icon || ((0, jsx_runtime_1.jsx)(lucide_react_1.Calendar, { className: "h-4 w-4 mr-2 text-primary" })), (0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)("text-sm font-bold", event.color ? `text-${event.color}` : "text-primary"), children: event.year })] })) : ((0, jsx_runtime_1.jsx)("p", { className: "text-lg font-bold text-primary mb-2", children: event.year })), (0, jsx_runtime_1.jsx)("h3", { className: "text-xl font-bold mb-1", children: event.title }), event.subtitle && ((0, jsx_runtime_1.jsx)("p", { className: "text-muted-foreground font-medium mb-2", children: event.subtitle })), (0, jsx_runtime_1.jsx)("p", { className: "text-muted-foreground", children: event.description })] }) }) })] }, event.id || index)); }) })] }) })] })); }; exports.ScrollTimeline = ScrollTimeline; //# sourceMappingURL=scroll-timeline.js.map