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.
216 lines (215 loc) • 10 kB
JavaScript
"use strict";
"use client";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ToggleTheme = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const lucide_react_1 = require("lucide-react");
const react_dom_1 = require("react-dom");
const utils_1 = require("@/components/lib/utils");
// 3. Component and export are renamed
const ToggleTheme = ({ className, duration = 400, animationType = "circle-spread", ...props }) => {
const [isDark, setIsDark] = (0, react_1.useState)(false);
const buttonRef = (0, react_1.useRef)(null);
(0, react_1.useEffect)(() => {
const updateTheme = () => {
setIsDark(document.documentElement.classList.contains("dark"));
};
updateTheme();
const observer = new MutationObserver(updateTheme);
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ["class"],
});
return () => observer.disconnect();
}, []);
const toggleTheme = (0, react_1.useCallback)(async () => {
if (!buttonRef.current)
return;
// Wait for the DOM update to complete within the View Transition
await document.startViewTransition(() => {
(0, react_dom_1.flushSync)(() => {
const newTheme = !isDark;
setIsDark(newTheme);
document.documentElement.classList.toggle("dark");
localStorage.setItem("theme", newTheme ? "dark" : "light");
});
}).ready;
// Calculate coordinates and dimensions for spatial animations
const { top, left, width, height } = buttonRef.current.getBoundingClientRect();
const x = left + width / 2;
const y = top + height / 2;
const maxRadius = Math.hypot(Math.max(left, window.innerWidth - left), Math.max(top, window.innerHeight - top));
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
// 4. Implement a switch to handle all animation types
switch (animationType) {
// --- Existing/Refined Types ---
case "circle-spread":
document.documentElement.animate({
clipPath: [
`circle(0px at ${x}px ${y}px)`,
`circle(${maxRadius}px at ${x}px ${y}px)`,
],
}, {
duration,
easing: "ease-in-out",
pseudoElement: "::view-transition-new(root)",
});
break;
case "round-morph":
document.documentElement.animate([
{ opacity: 0, transform: "scale(0.8) rotate(5deg)" },
{ opacity: 1, transform: "scale(1) rotate(0deg)" },
], {
duration: duration * 1.2,
easing: "cubic-bezier(0.68, -0.55, 0.265, 1.55)",
pseudoElement: "::view-transition-new(root)",
});
break;
case "swipe-left":
document.documentElement.animate({
clipPath: [
`inset(0 0 0 ${viewportWidth}px)`,
`inset(0 0 0 0)`,
],
}, {
duration,
easing: "cubic-bezier(0.2, 0, 0, 1)",
pseudoElement: "::view-transition-new(root)",
});
break;
case "swipe-up":
document.documentElement.animate({
clipPath: [
`inset(${viewportHeight}px 0 0 0)`,
`inset(0 0 0 0)`,
],
}, {
duration,
easing: "cubic-bezier(0.2, 0, 0, 1)",
pseudoElement: "::view-transition-new(root)",
});
break;
// --- New Advanced Types ---
case "diag-down-right":
document.documentElement.animate({
clipPath: [
`polygon(0 0, 0 0, 0 0, 0 0)`,
`polygon(0 0, 100% 0, 100% 100%, 0 100%)`,
],
}, {
duration: duration * 1.5,
easing: "cubic-bezier(0.4, 0, 0.2, 1)",
pseudoElement: "::view-transition-new(root)",
});
break;
case "fade-in-out":
document.documentElement.animate({
opacity: [0, 1],
}, {
duration: duration * 0.5,
easing: "ease-in-out",
pseudoElement: "::view-transition-new(root)",
});
break;
case "shrink-grow":
document.documentElement.animate([
{ transform: "scale(0.9)", opacity: 0 },
{ transform: "scale(1)", opacity: 1 },
], {
duration: duration * 1.2,
easing: "cubic-bezier(0.19, 1, 0.22, 1)",
pseudoElement: "::view-transition-new(root)",
});
document.documentElement.animate([
{ transform: "scale(1)", opacity: 1 },
{ transform: "scale(1.05)", opacity: 0 },
], {
duration: duration * 1.2,
easing: "cubic-bezier(0.19, 1, 0.22, 1)",
pseudoElement: "::view-transition-old(root)",
});
break;
case "flip-x-in":
const styleElement = document.createElement('style');
styleElement.textContent = `
::view-transition-group(root) { perspective: 1000px; }
::view-transition-old(root) { transform-origin: center; animation: flip-out 400ms forwards; }
::view-transition-new(root) { transform-origin: center; animation: flip-in 400ms forwards; }
@keyframes flip-out { from { transform: rotateY(0deg); opacity: 1; } to { transform: rotateY(-90deg); opacity: 0; } }
@keyframes flip-in { from { transform: rotateY(90deg); opacity: 0; } to { transform: rotateY(0deg); opacity: 1; } }
`;
document.head.appendChild(styleElement);
break;
case "split-vertical":
document.documentElement.animate([{ opacity: 0 }, { opacity: 1 }], {
duration: duration * 0.75,
easing: "ease-in",
pseudoElement: "::view-transition-new(root)",
});
document.documentElement.animate([
{ clipPath: 'inset(0 0 0 0)', transform: 'none' },
{ clipPath: 'inset(0 40% 0 40%)', transform: 'scale(1.2)' },
{ clipPath: 'inset(0 50% 0 50%)', transform: 'scale(1)' },
], {
duration: duration * 1.5,
easing: "cubic-bezier(0.68, -0.55, 0.265, 1.55)",
pseudoElement: "::view-transition-old(root)",
});
break;
// --- IMPLEMENTATION FOR MISSING TYPES ---
case "swipe-right":
document.documentElement.animate({
clipPath: [
`inset(0 ${viewportWidth}px 0 0)`,
`inset(0 0 0 0)`,
],
}, {
duration,
easing: "cubic-bezier(0.2, 0, 0, 1)",
pseudoElement: "::view-transition-new(root)",
});
break;
case "swipe-down":
document.documentElement.animate({
clipPath: [
`inset(0 0 ${viewportHeight}px 0)`,
`inset(0 0 0 0)`,
],
}, {
duration,
easing: "cubic-bezier(0.2, 0, 0, 1)",
pseudoElement: "::view-transition-new(root)",
});
break;
case "wave-ripple":
document.documentElement.animate({
clipPath: [
`circle(0% at 50% 50%)`,
`circle(${maxRadius}px at 50% 50%)`,
],
}, {
duration: duration * 1.5,
easing: "cubic-bezier(0.68, -0.55, 0.265, 1.55)",
pseudoElement: "::view-transition-new(root)",
});
break;
case "none":
default:
// No custom animation runs
break;
}
}, [isDark, duration, animationType]);
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("button", { ref: buttonRef, onClick: toggleTheme, className: (0, utils_1.cn)("p-2 rounded-full transition-colors duration-300", isDark ? "hover:text-amber-400" : "hover:text-primarylw", className), ...props, children: isDark ? (0, jsx_runtime_1.jsx)(lucide_react_1.Sun, { className: "h-6 w-6" }) : (0, jsx_runtime_1.jsx)(lucide_react_1.Moon, { className: "h-6 w-6" }) }), animationType !== 'flip-x-in' && ((0, jsx_runtime_1.jsx)("style", { dangerouslySetInnerHTML: {
__html: `
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
`,
} }))] }));
};
exports.ToggleTheme = ToggleTheme;
//# sourceMappingURL=toggle-theme.js.map