Initial Commit
This commit is contained in:
311
components/common/LayoutWrapper.jsx
Normal file
311
components/common/LayoutWrapper.jsx
Normal file
@ -0,0 +1,311 @@
|
||||
"use client";
|
||||
|
||||
import { usePathname } from "next/navigation";
|
||||
import React, { useEffect } from "react";
|
||||
import SplitText from "@/utlis/splitText";
|
||||
import gsap from "gsap";
|
||||
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
export default function LayoutWrapper({ children }) {
|
||||
const pathname = usePathname();
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
// Import the script only on the client side
|
||||
import("bootstrap/dist/js/bootstrap.esm").then(() => {
|
||||
// Module is imported, you can access any exported functionality if
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
let lastScrollTop = 0;
|
||||
const delta = 10;
|
||||
const header = document.querySelector(".header");
|
||||
|
||||
const handleScroll = () => {
|
||||
const scrollTop = window.scrollY;
|
||||
|
||||
if (scrollTop < 350) {
|
||||
header?.classList.remove("is-sticky");
|
||||
if (scrollTop < 200) {
|
||||
header?.classList.remove("header-sticky");
|
||||
} else {
|
||||
header?.classList.add("header-sticky");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (scrollTop > lastScrollTop + delta) {
|
||||
header?.classList.add("header-sticky");
|
||||
header?.classList.remove("is-sticky");
|
||||
} else if (scrollTop < lastScrollTop - delta) {
|
||||
header?.classList.add("is-sticky");
|
||||
}
|
||||
lastScrollTop = scrollTop;
|
||||
};
|
||||
setTimeout(() => {
|
||||
window.addEventListener("scroll", handleScroll);
|
||||
window.dispatchEvent(new Event("scroll"));
|
||||
});
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("scroll", handleScroll);
|
||||
};
|
||||
}, [pathname]);
|
||||
useEffect(() => {
|
||||
// Scrolling Effect
|
||||
const scrollingEffect = () => {
|
||||
const elements = document.querySelectorAll(".scrolling-effect");
|
||||
if (!elements.length) return;
|
||||
|
||||
elements.forEach((el) => {
|
||||
const settings = {
|
||||
scrollTrigger: {
|
||||
trigger: el,
|
||||
scrub: 3,
|
||||
toggleActions: "play none none reverse",
|
||||
start: "top bottom",
|
||||
end: "bottom bottom",
|
||||
delay: 3,
|
||||
},
|
||||
duration: 0.8,
|
||||
ease: "power3.out",
|
||||
};
|
||||
|
||||
if (el.classList.contains("effectRight")) {
|
||||
settings.opacity = 0;
|
||||
settings.x = "80";
|
||||
}
|
||||
if (el.classList.contains("effectLeft")) {
|
||||
settings.opacity = 0;
|
||||
settings.x = "-80";
|
||||
}
|
||||
if (el.classList.contains("effectBottom")) {
|
||||
settings.opacity = 0;
|
||||
settings.y = "100";
|
||||
}
|
||||
if (el.classList.contains("effectTop")) {
|
||||
settings.opacity = 0;
|
||||
settings.y = "-80";
|
||||
}
|
||||
if (el.classList.contains("effectZoomIn")) {
|
||||
settings.opacity = 0;
|
||||
settings.scale = 0.5;
|
||||
}
|
||||
|
||||
gsap.from(el, settings);
|
||||
});
|
||||
};
|
||||
|
||||
// Animation Text
|
||||
const animationText = () => {
|
||||
const splitTextElements = document.querySelectorAll(".split-text");
|
||||
if (!splitTextElements.length) return;
|
||||
|
||||
splitTextElements.forEach((el) => {
|
||||
const target = el.querySelector("p, a") || el;
|
||||
const pxlSplit = new SplitText(target, {
|
||||
type: "words, chars, lines",
|
||||
lineThreshold: 0.5,
|
||||
wordsClass: "word",
|
||||
linesClass: "split-line",
|
||||
});
|
||||
|
||||
// Handle gradient characters
|
||||
const gradientChars = el.querySelectorAll(".text-gradient > .word > *");
|
||||
if (gradientChars.length) {
|
||||
let offset = 0;
|
||||
gradientChars.forEach((char) => {
|
||||
const parent = char.parentElement;
|
||||
const parentWidth = parent.offsetWidth;
|
||||
|
||||
char.style.backgroundSize = `${parentWidth}px 100%`;
|
||||
offset += char.previousElementSibling?.offsetWidth || 0;
|
||||
char.style.backgroundPosition = `${parentWidth - offset}px 0%`;
|
||||
});
|
||||
}
|
||||
|
||||
let splitTypeSet = pxlSplit.chars;
|
||||
gsap.set(target, { perspective: 400 });
|
||||
|
||||
const settings = {
|
||||
scrollTrigger: {
|
||||
trigger: target,
|
||||
start: "top 86%",
|
||||
once: true,
|
||||
},
|
||||
duration: 0.9,
|
||||
stagger: 0.02,
|
||||
ease: "power3.out",
|
||||
};
|
||||
|
||||
const hasClass = (className) => el.classList.contains(className);
|
||||
|
||||
if (hasClass("effect-fade")) settings.opacity = 0;
|
||||
if (hasClass("effect-right")) {
|
||||
settings.opacity = 0;
|
||||
settings.x = "50";
|
||||
}
|
||||
if (hasClass("effect-left")) {
|
||||
settings.opacity = 0;
|
||||
settings.x = "-50";
|
||||
}
|
||||
if (hasClass("effect-up")) {
|
||||
settings.opacity = 0;
|
||||
settings.y = "80";
|
||||
}
|
||||
if (hasClass("effect-down")) {
|
||||
settings.opacity = 0;
|
||||
settings.y = "-80";
|
||||
}
|
||||
if (hasClass("effect-rotate")) {
|
||||
settings.opacity = 0;
|
||||
settings.rotateX = "50deg";
|
||||
}
|
||||
if (hasClass("effect-scale")) {
|
||||
settings.opacity = 0;
|
||||
settings.scale = "0.5";
|
||||
}
|
||||
|
||||
if (
|
||||
hasClass("split-lines-transform") ||
|
||||
hasClass("split-lines-rotation-x")
|
||||
) {
|
||||
pxlSplit.split({
|
||||
type: "lines",
|
||||
lineThreshold: 0.5,
|
||||
linesClass: "split-line",
|
||||
});
|
||||
|
||||
splitTypeSet = pxlSplit.lines;
|
||||
settings.opacity = 0;
|
||||
settings.stagger = 0.5;
|
||||
|
||||
if (hasClass("split-lines-rotation-x")) {
|
||||
settings.rotationX = -120;
|
||||
settings.transformOrigin = "top center -50";
|
||||
} else {
|
||||
settings.yPercent = 100;
|
||||
settings.autoAlpha = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasClass("split-words-scale")) {
|
||||
pxlSplit.split({ type: "words" });
|
||||
splitTypeSet = pxlSplit.words;
|
||||
|
||||
splitTypeSet.forEach((elw, index) => {
|
||||
gsap.set(
|
||||
elw,
|
||||
{
|
||||
opacity: 0,
|
||||
scale: index % 2 === 0 ? 0 : 2,
|
||||
force3D: true,
|
||||
duration: 0.1,
|
||||
ease: "power3.out",
|
||||
stagger: 0.02,
|
||||
},
|
||||
index * 0.01
|
||||
);
|
||||
});
|
||||
|
||||
gsap.to(splitTypeSet, {
|
||||
scrollTrigger: {
|
||||
trigger: el,
|
||||
start: "top 86%",
|
||||
},
|
||||
rotateX: "0",
|
||||
scale: 1,
|
||||
opacity: 1,
|
||||
});
|
||||
} else {
|
||||
gsap.from(splitTypeSet, settings);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Initialize effects
|
||||
setTimeout(() => {
|
||||
scrollingEffect();
|
||||
animationText();
|
||||
});
|
||||
}, [pathname]);
|
||||
useEffect(() => {
|
||||
const WOW = require("@/utlis/wow");
|
||||
const wow = new WOW.default({
|
||||
mobile: false,
|
||||
live: false,
|
||||
});
|
||||
wow.init();
|
||||
}, [pathname]);
|
||||
useEffect(() => {
|
||||
// Dynamically import Bootstrap
|
||||
import("bootstrap")
|
||||
.then((bootstrap) => {
|
||||
// Close any open modal
|
||||
const modalElements = document.querySelectorAll(".modal.show");
|
||||
modalElements.forEach((modal) => {
|
||||
const modalInstance = bootstrap.Modal.getInstance(modal);
|
||||
if (modalInstance) {
|
||||
modalInstance.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Close any open offcanvas
|
||||
const offcanvasElements = document.querySelectorAll(".offcanvas.show");
|
||||
offcanvasElements.forEach((offcanvas) => {
|
||||
const offcanvasInstance = bootstrap.Offcanvas.getInstance(offcanvas);
|
||||
if (offcanvasInstance) {
|
||||
offcanvasInstance.hide();
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error loading Bootstrap:", error);
|
||||
});
|
||||
}, [pathname]); // Runs every time the route changes
|
||||
useEffect(() => {
|
||||
const scrollTransformElements =
|
||||
document.querySelectorAll(".scroll-tranform");
|
||||
|
||||
if (scrollTransformElements.length > 0) {
|
||||
scrollTransformElements.forEach((element) => {
|
||||
const direction = element.dataset.direction || "up";
|
||||
const distance = element.dataset.distance || "10%";
|
||||
let animationProperty;
|
||||
|
||||
switch (direction.toLowerCase()) {
|
||||
case "left":
|
||||
animationProperty = { x: `-${distance}` };
|
||||
break;
|
||||
case "right":
|
||||
animationProperty = { x: `${distance}` };
|
||||
break;
|
||||
case "up":
|
||||
animationProperty = { y: `-${distance}` };
|
||||
break;
|
||||
case "down":
|
||||
animationProperty = { y: `${distance}` };
|
||||
break;
|
||||
default:
|
||||
animationProperty = { y: `-${distance}` };
|
||||
}
|
||||
|
||||
gsap.to(element, {
|
||||
...animationProperty,
|
||||
scrollTrigger: {
|
||||
trigger: element,
|
||||
start: "top center",
|
||||
end: "bottom top",
|
||||
scrub: 2,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Optional cleanup
|
||||
return () => {
|
||||
ScrollTrigger.getAll().forEach((trigger) => trigger.kill());
|
||||
};
|
||||
}, [pathname]);
|
||||
return <>{children}</>;
|
||||
}
|
||||
Reference in New Issue
Block a user