File size: 1,678 Bytes
ace9a3e
98051f8
ace9a3e
7bf1507
ace9a3e
a1a6daf
 
7bf1507
a1a6daf
 
 
7bf1507
a1a6daf
ace9a3e
7bf1507
 
 
 
 
 
 
 
a1a6daf
 
59de250
ace9a3e
6bb0e6c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ace9a3e
 
6bb0e6c
ace9a3e
 
 
 
 
 
 
725337f
ace9a3e
 
 
 
 
 
 
 
 
 
 
 
 
8918d96
98051f8
ace9a3e
a1a6daf
 
 
 
ace9a3e
725337f
a1a6daf
7bf1507
a1a6daf
f311ca9
ace9a3e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<script lang="ts">
	import { onDestroy } from "svelte";

	import CarbonCopy from "~icons/carbon/copy";

	interface Props {
		classNames?: string;
		iconClassNames?: string;
		value: string;
		children?: import("svelte").Snippet;
		onClick?: () => void;
		showTooltip?: boolean;
	}

	let {
		classNames = "",
		iconClassNames = "",
		value,
		children,
		onClick,
		showTooltip = true,
	}: Props = $props();

	let isSuccess = $state(false);
	let timeout: ReturnType<typeof setTimeout>;

	const unsecuredCopy = (text: string) => {
		//Old or insecure browsers

		const textArea = document.createElement("textarea");
		textArea.value = text;
		document.body.appendChild(textArea);
		textArea.focus();
		textArea.select();
		document.execCommand("copy");
		document.body.removeChild(textArea);

		return Promise.resolve();
	};

	const copy = async (text: string) => {
		if (window.isSecureContext && navigator.clipboard) {
			return navigator.clipboard.writeText(text);
		}
		return unsecuredCopy(text);
	};

	const handleClick = async () => {
		try {
			await copy(value);

			isSuccess = true;
			if (timeout) {
				clearTimeout(timeout);
			}
			timeout = setTimeout(() => {
				isSuccess = false;
			}, 500);
		} catch (err) {
			console.error(err);
		}
	};

	onDestroy(() => {
		if (timeout) {
			clearTimeout(timeout);
		}
	});
</script>

<button
	class={classNames}
	title={"Copy to clipboard"}
	type="button"
	onclick={() => {
		onClick?.();
		handleClick();
	}}
>
	<div class="relative transition-transform duration-200 {isSuccess ? 'scale-125' : 'scale-100'}">
		{#if children}{@render children()}{:else}
			<CarbonCopy class={iconClassNames} />
		{/if}
	</div>
</button>