/ src / lib / components / share-button / share-button.svelte
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>