| 625 | const pointerCopyTimes = new WeakMap<HTMLButtonElement, number>(); |
| 626 | |
| 627 | function writeClipboardWithSelection(value: string) { |
| 628 | let copied = false; |
| 629 | const onCopy = (event: ClipboardEvent) => { |
| 630 | event.clipboardData?.setData("text/plain", value); |
| 631 | event.preventDefault(); |
| 632 | copied = true; |
| 633 | }; |
| 634 | const textarea = document.createElement("textarea"); |
| 635 | textarea.value = value; |
| 636 | textarea.setAttribute("readonly", ""); |
| 637 | textarea.style.position = "fixed"; |
| 638 | textarea.style.top = "0"; |
| 639 | textarea.style.left = "0"; |
| 640 | textarea.style.width = "1px"; |
| 641 | textarea.style.height = "1px"; |
| 642 | textarea.style.opacity = "0"; |
| 643 | |
| 644 | document.body.appendChild(textarea); |
| 645 | window.focus(); |
| 646 | textarea.focus(); |
| 647 | textarea.select(); |
| 648 | textarea.setSelectionRange(0, value.length); |
| 649 | document.addEventListener("copy", onCopy); |
| 650 | |
| 651 | try { |
| 652 | return document.execCommand("copy") || copied; |
| 653 | } finally { |
| 654 | document.removeEventListener("copy", onCopy); |
| 655 | textarea.remove(); |
| 656 | } |
| 657 | } |
| 658 | |
| 659 | async function writeClipboard(value: string) { |
| 660 | if (writeClipboardWithSelection(value)) return true; |