File size: 1,743 Bytes
fd8a2ca
1d04bf7
fd8a2ca
4331e77
1d04bf7
fd8a2ca
21b8785
 
4331e77
21b8785
 
 
4331e77
21b8785
fd8a2ca
4331e77
 
 
 
 
 
 
 
21b8785
 
5c8753b
fd8a2ca
76a4d9b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fd8a2ca
 
76a4d9b
fd8a2ca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
536eb3a
1d04bf7
fd8a2ca
21b8785
 
 
 
fd8a2ca
68d3743
21b8785
4331e77
21b8785
68d3743
4331e77
 
 
68d3743
fd8a2ca
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
87
88
89
90
91
<script lang="ts">
	import { onDestroy } from "svelte";

	import CarbonCopy from "~icons/carbon/copy";
	import Tooltip from "./Tooltip.svelte";

	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;
			}, 1000);
		} 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">
		{#if children}{@render children()}{:else}
			<CarbonCopy class={iconClassNames} />
		{/if}

		{#if showTooltip}
			<Tooltip classNames={isSuccess ? "opacity-100" : "opacity-0"} />
		{/if}
	</div>
</button>