// Single event listener that checks which button's data to use document.addEventListener("copy", (event) => { const activeButtonData = buttonDataMap.get("active"); if (activeButtonData) { event.preventDefault(); event.clipboardData.setData( "application/json", JSON.stringify(activeButtonData) ); event.clipboardData.setData( "text/plain", JSON.stringify(activeButtonData) ); buttonDataMap.delete("active"); // Clear after copying } }); copybtn.forEach((btn) => { const url = btn.getAttribute("data-copy"); const text = btn.children[0].children[0]; const icon = btn.querySelector("svg"); let isAnimating = false; btn.onmouseenter = async () => { if (isAnimating) return; isAnimating = true; await gsap.to(icon, { rotate: "+=360", duration: 0.3, ease: "expo.out", }); isAnimating = false; }; btn.onclick = async (evt) => { try { const res = await fetch(url); let data = await res.text(); // Try to parse as JSON in case it's JSON data try { const jsonData = JSON.parse(data); buttonDataMap.set("active", jsonData); } catch { buttonDataMap.set("active", data); } // Trigger the copy command document.execCommand("copy"); text.textContent = "Copied!"; console.log("copied successfully"); setTimeout(() => { text.textContent = "Copy this"; }, 1000); } catch (error) { console.error("Failed to copy:", error); text.textContent = "Failed to copy"; setTimeout(() => { text.textContent = "Copy this"; }, 1000); } }; }); }; /** -- Split Text Button */ const split = (text, type = "chars") => { text.setAttribute("aria-label", text.textContent); const splits = new SplitText(text, { type }); splits[type].forEach((char) => char.setAttribute("aria-hidden", "true")); return splits[type]; }; const buttons = () => { const buttons = [...document.querySelectorAll("[data-module='btn']")]; buttons.forEach((btn) => { const overflow = btn.children[0]; const text = overflow.children[0]; overflow.appendChild(text.cloneNode(true)); const splitText1 = split(overflow.children[0], "chars"); const splitText2 = split(overflow.children[1], "chars"); const animation = { yPercent: "-=100", duration: 0.8, ease: "expo.out", stagger: 0.02, }; btn.onmouseenter = () => { gsap.to(splitText1, { ...animation, yPercent: -100 }); gsap.to(splitText2, { ...animation, yPercent: -100 }); }; btn.onmouseleave = () => { gsap.to(splitText1, { ...animation, yPercent: 0 }); gsap.to(splitText2, { ...animation, yPercent: 0 }); }; }); }; /** -- Controller */ addEventListener("GSAPReady", (event) => { copybtn(); // desktop only animations if (window.matchMedia("(min-width: 1024px)").matches) { buttons(); } }); }