53 lines
1.4 KiB
Plaintext
53 lines
1.4 KiB
Plaintext
---
|
|
interface Props {
|
|
value: string;
|
|
display?: string;
|
|
label?: string;
|
|
event?: string;
|
|
}
|
|
const { value, display = value, label = `copy ${value}`, event } = Astro.props;
|
|
---
|
|
|
|
<button
|
|
class="copy"
|
|
type="button"
|
|
data-copy={value}
|
|
aria-label={label}
|
|
data-umami-event={event}
|
|
>
|
|
<span class="copy__text">{display}</span>
|
|
<svg class="copy__icon" viewBox="0 0 24 24" aria-hidden="true">
|
|
<rect x="9" y="9" width="11" height="11" rx="2"></rect>
|
|
<path d="M5 15V5a2 2 0 0 1 2-2h10"></path>
|
|
</svg>
|
|
<svg class="copy__check" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path d="M20 6 9 17l-5-5"></path>
|
|
</svg>
|
|
<span class="tip" aria-hidden="true">copied</span>
|
|
</button>
|
|
|
|
<script>
|
|
document.querySelectorAll<HTMLButtonElement>("[data-copy]").forEach((btn) => {
|
|
if (btn.dataset.copyBound) return;
|
|
btn.dataset.copyBound = "1";
|
|
btn.addEventListener("click", async () => {
|
|
const val = btn.dataset.copy ?? "";
|
|
try {
|
|
await navigator.clipboard.writeText(val);
|
|
} catch {
|
|
const t = btn.querySelector(".copy__text");
|
|
if (t) {
|
|
const r = document.createRange();
|
|
r.selectNodeContents(t);
|
|
const sel = getSelection();
|
|
sel?.removeAllRanges();
|
|
sel?.addRange(r);
|
|
document.execCommand?.("copy");
|
|
}
|
|
}
|
|
btn.classList.add("copied");
|
|
setTimeout(() => btn.classList.remove("copied"), 1600);
|
|
});
|
|
});
|
|
</script>
|