Skip to main content
Glama
northernvariables

FedMCP - Federal Parliamentary Information

useShare.ts6.08 kB
/** * useShare Hook * * Provides share functionality with Web Share API support and fallbacks * for social media platforms, email, clipboard, and print. */ import { useState, useCallback, useEffect } from 'react'; export interface ShareData { url: string; title: string; description?: string; } export interface ShareMethods { shareNative: () => Promise<void>; copyToClipboard: () => Promise<void>; shareEmail: () => void; sharePrint: () => void; shareTwitter: () => void; shareFacebook: () => void; shareLinkedIn: () => void; shareReddit: () => void; shareEHSocial: () => void; shareThreads: () => void; } export interface UseShareReturn extends ShareMethods { isSupported: boolean; isLoading: boolean; isCopied: boolean; error: string | null; } export function useShare(shareData: ShareData): UseShareReturn { const [isSupported, setIsSupported] = useState(false); const [isLoading, setIsLoading] = useState(false); const [isCopied, setIsCopied] = useState(false); const [error, setError] = useState<string | null>(null); // Detect Web Share API support useEffect(() => { setIsSupported( typeof navigator !== 'undefined' && 'share' in navigator && navigator.canShare?.({ url: shareData.url, title: shareData.title }) !== false ); }, [shareData.url, shareData.title]); // Convert relative URLs to absolute const getAbsoluteUrl = useCallback((url: string): string => { if (url.startsWith('http')) { return url; } if (typeof window !== 'undefined') { return `${window.location.origin}${url}`; } return url; }, []); // Native Web Share API const shareNative = useCallback(async () => { if (!isSupported) { throw new Error('Web Share API not supported'); } setIsLoading(true); setError(null); try { await navigator.share({ url: getAbsoluteUrl(shareData.url), title: shareData.title, text: shareData.description, }); } catch (err) { // AbortError is thrown when user cancels - ignore it if (err instanceof Error && err.name !== 'AbortError') { setError(err.message); throw err; } } finally { setIsLoading(false); } }, [isSupported, shareData, getAbsoluteUrl]); // Copy to clipboard const copyToClipboard = useCallback(async () => { setIsLoading(true); setError(null); try { const absoluteUrl = getAbsoluteUrl(shareData.url); if (navigator.clipboard?.writeText) { await navigator.clipboard.writeText(absoluteUrl); } else { // Fallback for older browsers const textArea = document.createElement('textarea'); textArea.value = absoluteUrl; textArea.style.position = 'fixed'; textArea.style.left = '-999999px'; document.body.appendChild(textArea); textArea.focus(); textArea.select(); try { document.execCommand('copy'); } finally { document.body.removeChild(textArea); } } setIsCopied(true); setTimeout(() => setIsCopied(false), 3000); } catch (err) { const message = err instanceof Error ? err.message : 'Failed to copy'; setError(message); throw new Error(message); } finally { setIsLoading(false); } }, [shareData.url, getAbsoluteUrl]); // Email share const shareEmail = useCallback(() => { const subject = encodeURIComponent(shareData.title); const body = encodeURIComponent( `${shareData.description || ''}\n\n${getAbsoluteUrl(shareData.url)}` ); window.open(`mailto:?subject=${subject}&body=${body}`, '_blank'); }, [shareData, getAbsoluteUrl]); // Print functionality const sharePrint = useCallback(() => { window.print(); }, []); // Twitter/X share const shareTwitter = useCallback(() => { const url = getAbsoluteUrl(shareData.url); const text = encodeURIComponent(shareData.title); window.open( `https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${text}`, '_blank', 'width=550,height=420' ); }, [shareData, getAbsoluteUrl]); // Facebook share const shareFacebook = useCallback(() => { const url = getAbsoluteUrl(shareData.url); window.open( `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`, '_blank', 'width=550,height=420' ); }, [shareData.url, getAbsoluteUrl]); // LinkedIn share const shareLinkedIn = useCallback(() => { const url = getAbsoluteUrl(shareData.url); window.open( `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`, '_blank', 'width=550,height=420' ); }, [shareData.url, getAbsoluteUrl]); // Reddit share const shareReddit = useCallback(() => { const url = getAbsoluteUrl(shareData.url); const title = encodeURIComponent(shareData.title); window.open( `https://www.reddit.com/submit?url=${encodeURIComponent(url)}&title=${title}`, '_blank', 'width=550,height=420' ); }, [shareData, getAbsoluteUrl]); // EH! Social share const shareEHSocial = useCallback(() => { const url = getAbsoluteUrl(shareData.url); const text = encodeURIComponent(shareData.title); window.open( `https://eh.social/share?url=${encodeURIComponent(url)}&text=${text}`, '_blank', 'width=550,height=420' ); }, [shareData, getAbsoluteUrl]); // Threads share const shareThreads = useCallback(() => { const url = getAbsoluteUrl(shareData.url); const text = encodeURIComponent(`${shareData.title} ${url}`); window.open( `https://threads.net/intent/post?text=${text}`, '_blank', 'width=550,height=420' ); }, [shareData, getAbsoluteUrl]); return { isSupported, isLoading, isCopied, error, shareNative, copyToClipboard, shareEmail, sharePrint, shareTwitter, shareFacebook, shareLinkedIn, shareReddit, shareEHSocial, shareThreads, }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/northernvariables/FedMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server