"use client"; import React, { useEffect, useState, useRef } from "react"; import { Copy, Check } from "lucide-react"; import { useAnalytics } from "./analytics/useAnalytics"; import { motion, AnimatePresence } from "framer-motion"; export function TextSelectionShare() { const [isVisible, setIsVisible] = useState(false); const [position, setPosition] = useState({ x: 0, y: 0 }); const [selectedText, setSelectedText] = useState(""); const [copied, setCopied] = useState(false); const menuRef = useRef(null); const { trackEvent } = useAnalytics(); const selectionTimeoutRef = useRef(undefined); useEffect(() => { const handleSelection = () => { // Clear any pending timeout if (selectionTimeoutRef.current) { clearTimeout(selectionTimeoutRef.current); } // Small delay to ensure selection is complete selectionTimeoutRef.current = setTimeout(() => { const selection = window.getSelection(); const text = selection?.toString().trim(); if (text && text.length > 10) { const range = selection?.getRangeAt(0); const rect = range?.getBoundingClientRect(); if (rect) { // Position menu above selection, centered setPosition({ x: rect.left + rect.width / 2, y: rect.top + window.scrollY - 10, }); setSelectedText(text); setIsVisible(true); } } else { setIsVisible(false); setCopied(false); } }, 100); }; const handleClickOutside = (e: MouseEvent) => { if (menuRef.current && !menuRef.current.contains(e.target as Node)) { const selection = window.getSelection(); if (!selection?.toString()) { setIsVisible(false); setCopied(false); } } }; // Listen to both mouseup and selectionchange for better reliability document.addEventListener("mouseup", handleSelection); document.addEventListener("selectionchange", handleSelection); document.addEventListener("mousedown", handleClickOutside); return () => { document.removeEventListener("mouseup", handleSelection); document.removeEventListener("selectionchange", handleSelection); document.removeEventListener("mousedown", handleClickOutside); if (selectionTimeoutRef.current) { clearTimeout(selectionTimeoutRef.current); } }; }, []); const handleCopy = async () => { const url = window.location.href; const shareText = `"${selectedText}"\n\n${url}`; try { await navigator.clipboard.writeText(shareText); setCopied(true); trackEvent("text_selection_copied", { text_length: selectedText.length, url: url, }); setTimeout(() => { setIsVisible(false); setCopied(false); }, 1500); } catch (err) { console.error("Failed to copy:", err); } }; const handleShareX = () => { const url = window.location.href; const text = encodeURIComponent(`"${selectedText}"\n\n`); const shareUrl = `https://twitter.com/intent/tweet?text=${text}&url=${encodeURIComponent(url)}`; window.open(shareUrl, "_blank", "width=550,height=420"); trackEvent("text_selection_shared_x", { text_length: selectedText.length, url: url, }); setIsVisible(false); }; const handleShareLinkedIn = () => { const url = window.location.href; const shareUrl = `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`; window.open(shareUrl, "_blank", "width=550,height=420"); trackEvent("text_selection_shared_linkedin", { text_length: selectedText.length, url: url, }); setIsVisible(false); }; return ( {isVisible && (
{/* Arrow */}
)} ); }