({
targetId,
originalImageUrl,
fileName = "github-creature",
pixelRatio = 2,
}: DownloadDropdownProps)
| 21 | pixelRatio?: number; |
| 22 | } |
| 23 | |
| 24 | export default function DownloadDropdown({ |
| 25 | targetId, |
| 26 | originalImageUrl, |
| 27 | fileName = "github-creature", |
| 28 | pixelRatio = 2, |
| 29 | }: DownloadDropdownProps) { |
| 30 | const [isDownloading, setIsDownloading] = React.useState(false); |
| 31 | |
| 32 | const downloadCardWithEffects = React.useCallback(async () => { |
| 33 | const node = document.querySelector(`#${targetId}`); |
| 34 | if (!node) { |
| 35 | return; |
| 36 | } |
| 37 | |
| 38 | setIsDownloading(true); |
| 39 | try { |
| 40 | try { |
| 41 | await document.fonts?.ready; |
| 42 | } catch { |
| 43 | // ignore |
| 44 | } |
| 45 | |
| 46 | const dataUrl = await domToPng(node, { |
| 47 | onCloneNode: (cloned) => { |
| 48 | if (cloned instanceof HTMLElement) { |
| 49 | cloned.style.transform = "none"; |
| 50 | cloned.style.transformStyle = "flat"; |
| 51 | cloned.style.boxShadow = "none"; |
| 52 | } |
| 53 | }, |
| 54 | scale: pixelRatio, |
| 55 | }); |
| 56 | |
| 57 | const link = document.createElement("a"); |
| 58 | link.href = dataUrl; |
| 59 | link.download = `${fileName}-card.png`; |
| 60 | link.click(); |
| 61 | } catch (error) { |
| 62 | console.error("Failed to download card image", error); |
| 63 | } finally { |
| 64 | setIsDownloading(false); |
| 65 | } |
| 66 | }, [fileName, pixelRatio, targetId]); |
| 67 | |
| 68 | const downloadOriginalImage = React.useCallback(async () => { |
| 69 | setIsDownloading(true); |
| 70 | try { |
| 71 | const response = await fetch(originalImageUrl); |
| 72 | const blob = await response.blob(); |
| 73 | const url = URL.createObjectURL(blob); |
| 74 | |
| 75 | const link = document.createElement("a"); |
| 76 | link.href = url; |
| 77 | link.download = `${fileName}.png`; |
| 78 | link.click(); |
| 79 | |
| 80 | URL.revokeObjectURL(url); |
nothing calls this directly
no outgoing calls
no test coverage detected