Files
SkinbaseNova/resources/js/hooks/useWebShare.js
Gregor Klevze 90f244f264 feat: artwork share system with modal, native Web Share API, and tracking
- Add ArtworkShareModal with glassmorphism UI (Facebook, X, Pinterest, Email, Copy Link, Embed Code)
- Add ArtworkShareButton with lazy-loaded modal and native share fallback
- Add useWebShare hook abstracting navigator.share with AbortError handling
- Add ShareToast auto-dismissing notification component
- Add share() endpoint to ArtworkInteractionController (POST /api/artworks/{id}/share)
- Add artwork_shares migration for Phase 2 share tracking
- Refactor ArtworkActionBar to use new ArtworkShareButton component
2026-02-28 15:29:45 +01:00

42 lines
1.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useCallback, useMemo } from 'react'
/**
* useWebShare abstracts native Web Share API with a fallback callback.
*
* Usage:
* const { canNativeShare, share } = useWebShare({ onFallback })
* share({ title, text, url })
*
* If `navigator.share` is available the browser-native share sheet opens.
* Otherwise `onFallback({ title, text, url })` is called (e.g. open a modal).
*/
export default function useWebShare({ onFallback } = {}) {
const canNativeShare = useMemo(
() => typeof navigator !== 'undefined' && typeof navigator.share === 'function',
[],
)
const share = useCallback(
async ({ title, text, url }) => {
if (canNativeShare) {
try {
await navigator.share({ title, text, url })
return { shared: true, native: true }
} catch (err) {
// User cancelled the native share — don't fall through to modal
if (err?.name === 'AbortError') {
return { shared: false, native: true }
}
}
}
// Fallback — open modal
onFallback?.({ title, text, url })
return { shared: false, native: false }
},
[canNativeShare, onFallback],
)
return { canNativeShare, share }
}