useCopyToClipboard.ts 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  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(input: string, { target = document.body }: Options = {}) {
  23. const element = document.createElement('textarea');
  24. const previouslyFocusedElement = document.activeElement;
  25. element.value = input;
  26. element.setAttribute('readonly', '');
  27. (element.style as any).contain = 'strict';
  28. element.style.position = 'absolute';
  29. element.style.left = '-9999px';
  30. element.style.fontSize = '12pt';
  31. const selection = document.getSelection();
  32. let originalRange;
  33. if (selection && selection.rangeCount > 0) {
  34. originalRange = selection.getRangeAt(0);
  35. }
  36. target.append(element);
  37. element.select();
  38. element.selectionStart = 0;
  39. element.selectionEnd = input.length;
  40. let isSuccess = false;
  41. try {
  42. isSuccess = document.execCommand('copy');
  43. } catch (e) {
  44. throw new Error(e);
  45. }
  46. element.remove();
  47. if (originalRange && selection) {
  48. selection.removeAllRanges();
  49. selection.addRange(originalRange);
  50. }
  51. if (previouslyFocusedElement) {
  52. (previouslyFocusedElement as HTMLElement).focus();
  53. }
  54. return isSuccess;
  55. }