useCopyToClipboard.ts 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import { ref, watch } from "vue";
  2. import { isDef } from "/@/utils/is";
  3. interface Options {
  4. target?: HTMLElement;
  5. }
  6. export function useCopyToClipboard(initial?: string) {
  7. const clipboardRef = ref(initial || "");
  8. const isSuccessRef = ref(false);
  9. const copiedRef = ref(false);
  10. watch(
  11. clipboardRef,
  12. (str?: string) => {
  13. if (isDef(str)) {
  14. copiedRef.value = true;
  15. isSuccessRef.value = copyTextToClipboard(str);
  16. }
  17. },
  18. { immediate: !!initial, flush: "sync" }
  19. );
  20. return { clipboardRef, isSuccessRef, copiedRef };
  21. }
  22. export function copyTextToClipboard(
  23. input: string,
  24. { target = document.body }: Options = {}
  25. ) {
  26. const element = document.createElement("textarea");
  27. const previouslyFocusedElement = document.activeElement;
  28. element.value = input;
  29. element.setAttribute("readonly", "");
  30. (element.style as any).contain = "strict";
  31. element.style.position = "absolute";
  32. element.style.left = "-9999px";
  33. element.style.fontSize = "12pt";
  34. const selection = document.getSelection();
  35. let originalRange;
  36. if (selection && selection.rangeCount > 0) {
  37. originalRange = selection.getRangeAt(0);
  38. }
  39. target.append(element);
  40. element.select();
  41. element.selectionStart = 0;
  42. element.selectionEnd = input.length;
  43. let isSuccess = false;
  44. try {
  45. isSuccess = document.execCommand("copy");
  46. } catch (e) {
  47. throw new Error(e);
  48. }
  49. element.remove();
  50. if (originalRange && selection) {
  51. selection.removeAllRanges();
  52. selection.addRange(originalRange);
  53. }
  54. if (previouslyFocusedElement) {
  55. (previouslyFocusedElement as HTMLElement).focus();
  56. }
  57. return isSuccess;
  58. }