|
<script lang="ts"> |
|
import { onDestroy } from "svelte"; |
|
import { fade } from "svelte/transition"; |
|
import { Copy, Check } from "@gradio/icons"; |
|
|
|
let copied = false; |
|
export let value: string; |
|
let timer: ReturnType<typeof setTimeout>;; |
|
|
|
function copy_feedback(): void { |
|
copied = true; |
|
if (timer) clearTimeout(timer); |
|
timer = setTimeout(() => { |
|
copied = false; |
|
}, 2000); |
|
} |
|
|
|
async function handle_copy(): Promise<void> { |
|
if ("clipboard" in navigator) { |
|
await navigator.clipboard.writeText(value); |
|
copy_feedback(); |
|
} |
|
} |
|
|
|
onDestroy(() => { |
|
if (timer) clearTimeout(timer); |
|
}); |
|
</script> |
|
|
|
<button |
|
on:click={handle_copy} |
|
title="Copy text to clipboard" |
|
class:copied |
|
aria-roledescription="Copy value" |
|
aria-label="Copy" |
|
> |
|
<Copy /> |
|
{#if copied} |
|
<span |
|
class="check" |
|
transition:fade |
|
aria-roledescription="Value copied" |
|
aria-label="Copied"><Check /></span |
|
> |
|
{/if} |
|
</button> |
|
|
|
<style> |
|
button { |
|
position: relative; |
|
cursor: pointer; |
|
padding: 5px; |
|
width: 22px; |
|
height: 22px; |
|
} |
|
|
|
.check { |
|
position: absolute; |
|
top: 0; |
|
right: 0; |
|
z-index: var(--layer-top); |
|
background: var(--background-fill-primary); |
|
padding: var(--size-1); |
|
width: 100%; |
|
height: 100%; |
|
color: var(--body-text-color); |
|
} |
|
</style> |