gradio
1<script lang="ts">
2import { onDestroy } from "svelte";
3import { Copy, Check } from "@gradio/icons";
4
5let copied = false;
6export let value: string;
7let timer: NodeJS.Timeout;
8
9function copy_feedback(): void {
10copied = true;
11if (timer) clearTimeout(timer);
12timer = setTimeout(() => {
13copied = false;
14}, 2000);
15}
16
17async function handle_copy(): Promise<void> {
18if ("clipboard" in navigator) {
19await navigator.clipboard.writeText(value);
20copy_feedback();
21} else {
22const textArea = document.createElement("textarea");
23textArea.value = value;
24
25textArea.style.position = "absolute";
26textArea.style.left = "-999999px";
27
28document.body.prepend(textArea);
29textArea.select();
30
31try {
32document.execCommand("copy");
33copy_feedback();
34} catch (error) {
35console.error(error);
36} finally {
37textArea.remove();
38}
39}
40}
41
42onDestroy(() => {
43if (timer) clearTimeout(timer);
44});
45</script>
46
47<button
48on:click={handle_copy}
49class="action"
50title="copy"
51aria-label={copied ? "Copied message" : "Copy message"}
52>
53{#if !copied}
54<Copy />
55{/if}
56{#if copied}
57<Check />
58{/if}
59</button>
60
61<style>
62button {
63position: relative;
64top: 0;
65right: 0;
66cursor: pointer;
67color: var(--body-text-color-subdued);
68margin-right: 5px;
69}
70
71button:hover {
72color: var(--body-text-color);
73}
74
75.action {
76width: 15px;
77height: 14px;
78}
79</style>
80