310 lines
15 KiB
TypeScript
310 lines
15 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect, useRef } from "react";
|
|
import gsap from "gsap";
|
|
import { ShimmerText } from "@/animations/Reveal";
|
|
import { preload } from "react-dom";
|
|
|
|
export default function IndexHero() {
|
|
preload("/images/home-bg-1.webp", { as: "image" });
|
|
const [activeSlide, setActiveSlide] = useState(0);
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
|
|
// Auto-slide every 7 seconds — slower, more readable, professional pacing
|
|
useEffect(() => {
|
|
const interval = setInterval(() => {
|
|
setActiveSlide((prev) => (prev === 0 ? 1 : 0));
|
|
}, 7000);
|
|
return () => clearInterval(interval);
|
|
}, []);
|
|
|
|
const handleDotClick = (index: number) => {
|
|
setActiveSlide(index);
|
|
};
|
|
|
|
// GSAP slide transition effect
|
|
useEffect(() => {
|
|
if (!containerRef.current) return;
|
|
|
|
// Find the currently active slide inside the container
|
|
const activeItem = containerRef.current.querySelector(".owl-item.active");
|
|
if (!activeItem) return;
|
|
|
|
const heading = activeItem.querySelector(".heading-content");
|
|
const text = activeItem.querySelector(".text-content");
|
|
|
|
if (heading && text) {
|
|
// Clear previous animations if any
|
|
gsap.killTweensOf([heading, text]);
|
|
|
|
// Premium elegant reveal with cubic elastic feel
|
|
gsap.fromTo(
|
|
heading,
|
|
{ y: 55, opacity: 0, scale: 0.95 },
|
|
{ y: 0, opacity: 1, scale: 1, duration: 1.1, ease: "power4.out" }
|
|
);
|
|
|
|
gsap.fromTo(
|
|
text,
|
|
{ y: 30, opacity: 0 },
|
|
{ y: 0, opacity: 1, duration: 0.95, ease: "power3.out", delay: 0.25 }
|
|
);
|
|
}
|
|
}, [activeSlide]);
|
|
|
|
return (
|
|
<div className="elementor-element elementor-element-741f56c e-con-full e-flex cut-corner-no sticky-container-off e-con e-parent" data-id="741f56c" data-element_type="container" data-e-type="container">
|
|
|
|
<style dangerouslySetInnerHTML={{ __html: `
|
|
/* Fluid responsive font size override for hero headings */
|
|
.logico-content-slider-widget .content-slider-item-heading {
|
|
font-size: clamp(30px, 5.5vw, 80px) !important;
|
|
word-wrap: break-word !important;
|
|
overflow-wrap: break-word !important;
|
|
white-space: normal !important;
|
|
}
|
|
|
|
/* Prevent horizontal overflow on slider and stage containers */
|
|
.logico-content-slider-widget,
|
|
.content-slider-wrapper,
|
|
.content-slider-container,
|
|
.content-slider,
|
|
.owl-stage-outer,
|
|
.owl-stage,
|
|
.owl-item,
|
|
.slider-item,
|
|
.slide-content,
|
|
.slide-content-inner {
|
|
width: 100% !important;
|
|
max-width: 100% !important;
|
|
box-sizing: border-box !important;
|
|
}
|
|
|
|
/* Force word wrapping and responsive spacing for heading and text */
|
|
.logico-content-slider-widget .content-slider-item-heading,
|
|
.logico-content-slider-widget .content-slider-item-heading span,
|
|
.logico-content-slider-widget .content-slider-item-heading .heading-content {
|
|
white-space: normal !important;
|
|
word-wrap: break-word !important;
|
|
overflow-wrap: break-word !important;
|
|
max-width: 100% !important;
|
|
}
|
|
|
|
.logico-content-slider-widget .content-slider-item-heading {
|
|
padding-left: 15px !important;
|
|
padding-right: 15px !important;
|
|
}
|
|
|
|
.logico-content-slider-widget .text-content {
|
|
width: 100% !important;
|
|
max-width: min(780px, 100%) !important;
|
|
box-sizing: border-box !important;
|
|
padding-left: 15px !important;
|
|
padding-right: 15px !important;
|
|
}
|
|
|
|
/* Larger, more readable hero subtitle on large/4K screens */
|
|
.logico-content-slider-widget .content-slider-item-text p {
|
|
font-size: clamp(16px, 1.35vw, 23px) !important;
|
|
line-height: 1.65 !important;
|
|
}
|
|
|
|
/* Responsive slider heights */
|
|
.logico-content-slider-widget .owl-stage-outer {
|
|
height: 800px !important;
|
|
}
|
|
|
|
@media (max-width: 840px) {
|
|
.logico-content-slider-widget .owl-stage-outer {
|
|
height: 600px !important;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
.logico-content-slider-widget .owl-stage-outer {
|
|
height: 520px !important;
|
|
margin-top: 7px !important;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 660px) {
|
|
.logico-content-slider-widget .content-slider-item-heading {
|
|
font-size: clamp(20px, 7vw, 32px) !important;
|
|
}
|
|
}
|
|
|
|
/* Slide counter ("01/02" + progress line): site.css pushes it ~80px in
|
|
from the right and only 9px off the bottom on mobile, so it sits in an
|
|
awkward spot. Pin it cleanly to the bottom-right with even padding. */
|
|
@media (max-width: 767px) {
|
|
.elementor-61 .elementor-element.elementor-element-6c7cbcb .slider-footer {
|
|
text-align: right !important;
|
|
margin-bottom: 24px !important;
|
|
}
|
|
.elementor-61 .elementor-element.elementor-element-6c7cbcb .slider-footer .slider-pagination {
|
|
justify-content: flex-end !important;
|
|
margin-left: 22px !important;
|
|
margin-right: 22px !important;
|
|
}
|
|
.elementor-61 .elementor-element.elementor-element-6c7cbcb .slider-progress-wrapper {
|
|
margin-right: 0 !important;
|
|
}
|
|
/* The prev/next arrows sit in the bottom-right corner and overlap the
|
|
counter once it's pinned right. Hide them on mobile — slides
|
|
auto-rotate and the counter shows progress. */
|
|
.elementor-61 .elementor-element.elementor-element-6c7cbcb .owl-nav {
|
|
display: none !important;
|
|
}
|
|
}
|
|
`}} />
|
|
<div className="elementor-element elementor-element-6c7cbcb elementor-widget elementor-widget-logico_content_slider" data-id="6c7cbcb" data-element_type="widget" data-e-type="widget" data-widget_type="logico_content_slider.default">
|
|
<div className="elementor-widget-container">
|
|
<div className="logico-content-slider-widget">
|
|
<div className="content-slider-wrapper">
|
|
<div className="content-slider-container">
|
|
<div className="content-slider owl-carousel owl-theme nav-view-vertical nav-h-position-right nav-v-position-bottom owl-loaded owl-drag" ref={containerRef}>
|
|
<div className="owl-stage-outer" style={{ position: "relative", overflow: "hidden" }}>
|
|
<div className="owl-stage" style={{ position: "relative", width: "100%", height: "100%" }}>
|
|
|
|
{/* Slide 1 */}
|
|
<div
|
|
className={`owl-item ${activeSlide === 0 ? "active" : ""}`}
|
|
style={{
|
|
position: "relative",
|
|
width: "100%",
|
|
opacity: activeSlide === 0 ? 1 : 0,
|
|
visibility: activeSlide === 0 ? "visible" : "hidden",
|
|
transition: "opacity 0.8s ease-in-out, visibility 0.8s ease-in-out",
|
|
zIndex: activeSlide === 0 ? 2 : 1
|
|
}}
|
|
>
|
|
<div
|
|
className="content-item slider-item elementor-repeater-item-3264830 slide-style-standard"
|
|
style={{
|
|
backgroundImage: "url('/images/home-bg-1.webp')",
|
|
backgroundPosition: "center center",
|
|
backgroundRepeat: "no-repeat",
|
|
backgroundSize: "cover"
|
|
}}
|
|
>
|
|
<div className="slide-content" style={{ display: "flex", flexDirection: "column", justifyContent: "center", alignItems: "center", width: "100%", height: "100%" }}>
|
|
<div className="slide-content-inner" style={{ display: "flex", flexDirection: "column", justifyContent: "center", alignItems: "center", textAlign: "center", margin: "0 auto", width: "100%", maxWidth: "1000px" }}>
|
|
<h1 className="content-slider-item-heading logico-content-wrapper-1" style={{ textAlign: "center", width: "100%" }}>
|
|
<span className="heading-content block">
|
|
ONE CONNECTED SYSTEM.<br />
|
|
<ShimmerText className="font-extrabold">ONE PROMISE KEPT.</ShimmerText>
|
|
</span>
|
|
</h1>
|
|
<div className="content-slider-item-text logico-content-wrapper-2" style={{ display: "flex", justifyContent: "center", width: "100%", marginTop: "23px" }}>
|
|
<div className="text-content" style={{ textAlign: "center", maxWidth: "680px", margin: "0 auto" }}>
|
|
<p>Stop managing three separate logistics services. Doormile unifies first, mid and last mile into a single intelligent delivery system powered by MileTruth™ AI.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Slide 2 */}
|
|
<div
|
|
className={`owl-item ${activeSlide === 1 ? "active" : ""}`}
|
|
style={{
|
|
position: "absolute",
|
|
top: 0,
|
|
left: 0,
|
|
width: "100%",
|
|
opacity: activeSlide === 1 ? 1 : 0,
|
|
visibility: activeSlide === 1 ? "visible" : "hidden",
|
|
transition: "opacity 0.8s ease-in-out, visibility 0.8s ease-in-out",
|
|
zIndex: activeSlide === 1 ? 2 : 1
|
|
}}
|
|
>
|
|
<div
|
|
className="content-item slider-item elementor-repeater-item-6867061 slide-style-standard"
|
|
style={{
|
|
backgroundImage: "url('/images/home-bg-1.webp')",
|
|
backgroundPosition: "center center",
|
|
backgroundRepeat: "no-repeat",
|
|
backgroundSize: "cover"
|
|
}}
|
|
>
|
|
<div className="slide-content" style={{ display: "flex", flexDirection: "column", justifyContent: "center", alignItems: "center", width: "100%", height: "100%" }}>
|
|
<div className="slide-content-inner" style={{ display: "flex", flexDirection: "column", justifyContent: "center", alignItems: "center", textAlign: "center", margin: "0 auto", width: "100%", maxWidth: "1000px" }}>
|
|
<h1 className="content-slider-item-heading logico-content-wrapper-1" style={{ textAlign: "center", width: "100%" }}>
|
|
<span className="heading-content block">
|
|
<ShimmerText className="font-extrabold">AI-POWERED</ShimmerText><br />
|
|
CONNECTED LOGISTICS
|
|
</span>
|
|
</h1>
|
|
<div className="content-slider-item-text logico-content-wrapper-2" style={{ display: "flex", justifyContent: "center", width: "100%", marginTop: "23px" }}>
|
|
<div className="text-content" style={{ textAlign: "center", maxWidth: "680px", margin: "0 auto" }}>
|
|
<p>Behind every successful business is a strong supply chain. Logistics turns plans into reality.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
{/* Navigation controls */}
|
|
<div className="owl-nav">
|
|
<button
|
|
type="button"
|
|
className="owl-next"
|
|
onClick={() => setActiveSlide((prev) => (prev === 0 ? 1 : 0))}
|
|
aria-label="Next"
|
|
style={{ cursor: "pointer", border: "none", outline: "none" }}
|
|
/>
|
|
<button
|
|
type="button"
|
|
className="owl-prev"
|
|
onClick={() => setActiveSlide((prev) => (prev === 0 ? 1 : 0))}
|
|
aria-label="Previous"
|
|
style={{ cursor: "pointer", border: "none", outline: "none" }}
|
|
/>
|
|
</div>
|
|
|
|
{/* Slider Progress Controls */}
|
|
<div className="slider-footer slider-footer-position-after slider-footer-width-full slider-footer-view-inside">
|
|
<div className="slider-footer-content">
|
|
<div className="slider-pagination" style={{ display: "flex", justifyContent: "flex-end", alignItems: "center" }}>
|
|
<div className="slider-progress-wrapper" style={{ marginRight: "35px", display: "flex", flexDirection: "column", alignItems: "flex-start" }}>
|
|
<div style={{ fontSize: "16px", fontWeight: 600, color: "#FFFFFF", marginBottom: "4px" }}>
|
|
<span className="slider-progress-current">{activeSlide === 0 ? "01" : "02"}</span>
|
|
{" / "}
|
|
<span className="slider-progress-all" style={{ opacity: 0.6 }}>02</span>
|
|
</div>
|
|
{/* Progress Line */}
|
|
<div style={{ width: "80px", height: "2px", background: "rgba(255, 255, 255, 0.2)", position: "relative", borderRadius: "1px", overflow: "hidden" }}>
|
|
<div style={{
|
|
position: "absolute",
|
|
left: activeSlide === 0 ? "0" : "50%",
|
|
width: "50%",
|
|
height: "100%",
|
|
background: "#c01227",
|
|
transition: "left 0.3s ease"
|
|
}} />
|
|
</div>
|
|
</div>
|
|
{/* Dots are hidden to match production */}
|
|
<div className="owl-dots owl-dots-6c7cbcb" style={{ display: "none" }}>
|
|
<button type="button" className={`owl-dot ${activeSlide === 0 ? "active" : ""}`} onClick={() => handleDotClick(0)}><span></span></button>
|
|
<button type="button" className={`owl-dot ${activeSlide === 1 ? "active" : ""}`} onClick={() => handleDotClick(1)}><span></span></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|