share-button.svelte
1 <script lang="ts"> 2 import { run } from 'svelte/legacy'; 3 4 import ShareIcon from '$lib/components/icons/Sharrow.svelte'; 5 import Button from '../button/button.svelte'; 6 import { type ComponentProps } from 'svelte'; 7 import modal from '$lib/stores/modal'; 8 import shareSteps from '$lib/flows/share/share-steps'; 9 import Stepper from '$lib/components/stepper/stepper.svelte'; 10 import { browser } from '$app/environment'; 11 12 interface Props { 13 text?: string | undefined; 14 url: string; 15 disabled?: boolean; 16 downloadableImageUrl?: string; 17 shareModalText?: string | undefined; 18 buttonVariant?: ComponentProps<typeof Button>['variant']; 19 supportButtonOptions?: Parameters<typeof shareSteps>[0]['supportButtonOptions'] | undefined; 20 shareLabel?: string; 21 } 22 23 let { 24 text = undefined, 25 url, 26 disabled = false, 27 downloadableImageUrl = '', 28 shareModalText = undefined, 29 buttonVariant = 'ghost', 30 supportButtonOptions = undefined, 31 shareLabel = 'Share', 32 }: Props = $props(); 33 34 async function preloadImage(url: string) { 35 try { 36 const img = new Image(); 37 img.src = url; 38 await img.decode(); 39 } catch (error) { 40 // we don't really care to make a big fuss about this 41 // eslint-disable-next-line no-console 42 console.error('Error preloading image', error); 43 } 44 } 45 46 run(() => { 47 browser && downloadableImageUrl && preloadImage(downloadableImageUrl); 48 }); 49 50 function handleClick() { 51 modal.show( 52 Stepper, 53 undefined, 54 shareSteps({ 55 text, 56 url, 57 downloadableImageUrl, 58 shareModalText, 59 supportButtonOptions, 60 }), 61 ); 62 } 63 </script> 64 65 <Button {disabled} variant={buttonVariant} onclick={handleClick}> 66 <div class="button-inner"> 67 <ShareIcon style="fill:currentColor" /> 68 {shareLabel} 69 </div> 70 </Button> 71 72 <style> 73 .button-inner { 74 display: flex; 75 align-items: center; 76 gap: 0.125rem; 77 margin-left: -0.25rem; 78 } 79 </style>