|
1 | 1 | <script lang="ts"> |
2 | | - import { page } from '$app/stores'; |
| 2 | + import { page } from '$app/state'; |
3 | 3 | import { getPageMarkdown } from '$lib/remote/markdown.remote'; |
4 | 4 | import { copyToClipboard } from '$lib/utils/copy'; |
5 | | - import { cn } from '$lib/utils/cn'; |
6 | | - import { writable } from 'svelte/store'; |
7 | 5 | import { Button, Icon, SplitButton } from '$lib/components/ui'; |
8 | 6 | import { Tooltip } from '$lib/components'; |
9 | 7 | import { createDropdownMenu, melt } from '@melt-ui/svelte'; |
10 | 8 |
|
11 | | - interface CopyAsMarkdownProps { |
| 9 | + interface Props { |
12 | 10 | class?: string; |
13 | 11 | } |
14 | 12 |
|
15 | | - const { class: classNames }: CopyAsMarkdownProps = $props(); |
| 13 | + const { class: classNames }: Props = $props(); |
16 | 14 |
|
17 | | - const markdown = getPageMarkdown($page.route.id); |
18 | | - const copied = writable(false); |
| 15 | + let copied = $state(false); |
| 16 | + let copying = $state(false); |
19 | 17 | let timeout: ReturnType<typeof setTimeout> | undefined = undefined; |
20 | 18 |
|
21 | | - const copy = () => { |
| 19 | + async function copy() { |
| 20 | + copying = true; |
22 | 21 | if (timeout) clearTimeout(timeout); |
23 | | - copyToClipboard(markdown.current ?? ''); |
24 | | - copied.set(true); |
25 | | - timeout = setTimeout(() => copied.set(false), 2000); |
26 | | - }; |
| 22 | + const markdown = await getPageMarkdown(page.route.id); |
| 23 | + copyToClipboard(markdown ?? ''); |
| 24 | + timeout = setTimeout(() => (copied = false), 2000); |
| 25 | + copied = true; |
| 26 | + copying = false; |
| 27 | + } |
27 | 28 |
|
28 | | - const resetCopied = () => { |
| 29 | + function resetCopied() { |
29 | 30 | if (timeout) clearTimeout(timeout); |
30 | | - copied.set(false); |
31 | | - }; |
| 31 | + copied = false; |
| 32 | + } |
32 | 33 |
|
33 | | - const copyAndClose = () => { |
| 34 | + function copyAndClose() { |
34 | 35 | copy(); |
35 | 36 | open.set(false); |
36 | | - }; |
| 37 | + } |
37 | 38 |
|
38 | 39 | const { |
39 | 40 | elements: { trigger, menu }, |
|
50 | 51 | }; |
51 | 52 | </script> |
52 | 53 |
|
53 | | -{#if !markdown.loading && markdown.current} |
54 | | - <div class={cn('copy-ctl inline-flex items-center', classNames)}> |
55 | | - <SplitButton> |
56 | | - <Tooltip disabled={!$copied}> |
57 | | - <Button |
58 | | - variant="secondary" |
59 | | - onclick={copy} |
60 | | - onmouseleave={resetCopied} |
61 | | - aria-label="Copy page as Markdown" |
62 | | - splitPosition="first" |
63 | | - class="text-sm" |
64 | | - > |
65 | | - <Icon name="copy" aria-hidden="true" class="text-sm" /> |
66 | | - <span>Copy page</span> |
67 | | - </Button> |
68 | | - {#snippet tooltip()} |
69 | | - Copied |
70 | | - {/snippet} |
71 | | - </Tooltip> |
72 | | - |
73 | | - <button |
74 | | - class="web-button is-secondary is-split is-split-last text-sm" |
75 | | - use:melt={$trigger} |
76 | | - aria-label="Open options" |
| 54 | +<div class={['copy-ctl inline-flex items-center', classNames]}> |
| 55 | + <SplitButton> |
| 56 | + <Tooltip disabled={!copied}> |
| 57 | + <Button |
| 58 | + variant="secondary" |
| 59 | + disabled={copying} |
| 60 | + onclick={copy} |
| 61 | + onmouseleave={resetCopied} |
| 62 | + aria-label="Copy page as Markdown" |
| 63 | + splitPosition="first" |
| 64 | + class="text-sm" |
77 | 65 | > |
78 | | - {#if $open} |
79 | | - <span class="web-icon-chevron-up" aria-hidden="true"></span> |
80 | | - {:else} |
81 | | - <span class="web-icon-chevron-down" aria-hidden="true"></span> |
82 | | - {/if} |
83 | | - </button> |
84 | | - </SplitButton> |
| 66 | + <Icon name="copy" aria-hidden="true" class="text-sm" /> |
| 67 | + <span>Copy page</span> |
| 68 | + </Button> |
| 69 | + {#snippet tooltip()} |
| 70 | + Copied |
| 71 | + {/snippet} |
| 72 | + </Tooltip> |
| 73 | + |
| 74 | + <button |
| 75 | + class="web-button is-secondary is-split is-split-last text-sm" |
| 76 | + use:melt={$trigger} |
| 77 | + aria-label="Open options" |
| 78 | + > |
| 79 | + {#if $open} |
| 80 | + <span class="web-icon-chevron-up" aria-hidden="true"></span> |
| 81 | + {:else} |
| 82 | + <span class="web-icon-chevron-down" aria-hidden="true"></span> |
| 83 | + {/if} |
| 84 | + </button> |
| 85 | + </SplitButton> |
85 | 86 |
|
86 | | - {#if $open} |
87 | | - <div class="menu-wrapper web-select-menu is-normal menu z-1" use:melt={$menu}> |
88 | | - <ul class="text-sub-body"> |
89 | | - <li> |
90 | | - <button type="button" class="menu-btn text-sm" onclick={copyAndClose}> |
91 | | - <Icon name="copy" aria-hidden="true" class="text-sm" /> |
92 | | - <span>Copy as Markdown</span> |
93 | | - </button> |
94 | | - </li> |
95 | | - <li> |
96 | | - <button |
97 | | - type="button" |
98 | | - class="menu-btn text-sm" |
99 | | - onclick={() => { |
100 | | - viewInNewTab(); |
101 | | - open.set(false); |
102 | | - }} |
103 | | - > |
104 | | - <Icon name="external-icon" aria-hidden="true" class="text-sm" /> |
105 | | - <span>View as Markdown</span> |
106 | | - </button> |
107 | | - </li> |
108 | | - </ul> |
109 | | - </div> |
110 | | - {/if} |
111 | | - </div> |
112 | | -{/if} |
| 87 | + {#if $open} |
| 88 | + <div class="menu-wrapper web-select-menu is-normal menu z-1" use:melt={$menu}> |
| 89 | + <ul class="text-sub-body"> |
| 90 | + <li> |
| 91 | + <button type="button" class="menu-btn text-sm" onclick={copyAndClose}> |
| 92 | + <Icon name="copy" aria-hidden="true" class="text-sm" /> |
| 93 | + <span>Copy as Markdown</span> |
| 94 | + </button> |
| 95 | + </li> |
| 96 | + <li> |
| 97 | + <button |
| 98 | + type="button" |
| 99 | + class="menu-btn text-sm" |
| 100 | + onclick={() => { |
| 101 | + viewInNewTab(); |
| 102 | + open.set(false); |
| 103 | + }} |
| 104 | + > |
| 105 | + <Icon name="external-icon" aria-hidden="true" class="text-sm" /> |
| 106 | + <span>View as Markdown</span> |
| 107 | + </button> |
| 108 | + </li> |
| 109 | + </ul> |
| 110 | + </div> |
| 111 | + {/if} |
| 112 | +</div> |
113 | 113 |
|
114 | 114 | <style> |
115 | 115 | .copy-ctl { |
|
0 commit comments