mirror of
				https://github.com/CorentinTh/it-tools.git
				synced 2025-11-03 18:37:00 -05:00 
			
		
		
		
	feat(copy): support legacy copy to clipboard for older browser (#581)
This commit is contained in:
		
							parent
							
								
									76b2761d62
								
							
						
					
					
						commit
						6f93cba3da
					
				@ -10,5 +10,12 @@ module.exports = {
 | 
				
			|||||||
    '@typescript-eslint/semi': ['error', 'always'],
 | 
					    '@typescript-eslint/semi': ['error', 'always'],
 | 
				
			||||||
    '@typescript-eslint/no-use-before-define': ['error', { allowNamedExports: true, functions: false }],
 | 
					    '@typescript-eslint/no-use-before-define': ['error', { allowNamedExports: true, functions: false }],
 | 
				
			||||||
    'vue/no-empty-component-block': ['error'],
 | 
					    'vue/no-empty-component-block': ['error'],
 | 
				
			||||||
 | 
					    'no-restricted-imports': ['error', {
 | 
				
			||||||
 | 
					      paths: [{
 | 
				
			||||||
 | 
					        name: '@vueuse/core',
 | 
				
			||||||
 | 
					        importNames: ['useClipboard'],
 | 
				
			||||||
 | 
					        message: 'Please use local useCopy from src/composable/copy.ts instead of useClipboard.',
 | 
				
			||||||
 | 
					      }],
 | 
				
			||||||
 | 
					    }],
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -1,22 +1,13 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { useClipboard, useVModel } from '@vueuse/core';
 | 
					import { useVModel } from '@vueuse/core';
 | 
				
			||||||
 | 
					import { useCopy } from '@/composable/copy';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = defineProps<{ value: string }>();
 | 
					const props = defineProps<{ value: string }>();
 | 
				
			||||||
const emit = defineEmits(['update:value']);
 | 
					const emit = defineEmits(['update:value']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const value = useVModel(props, 'value', emit);
 | 
					const value = useVModel(props, 'value', emit);
 | 
				
			||||||
const tooltipText = ref('Copy to clipboard');
 | 
					const { copy, isJustCopied } = useCopy({ source: value, createToast: false });
 | 
				
			||||||
 | 
					const tooltipText = computed(() => isJustCopied.value ? 'Copied!' : 'Copy to clipboard');
 | 
				
			||||||
const { copy } = useClipboard({ source: value });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function onCopyClicked() {
 | 
					 | 
				
			||||||
  copy();
 | 
					 | 
				
			||||||
  tooltipText.value = 'Copied!';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  setTimeout(() => {
 | 
					 | 
				
			||||||
    tooltipText.value = 'Copy to clipboard';
 | 
					 | 
				
			||||||
  }, 2000);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
@ -24,7 +15,7 @@ function onCopyClicked() {
 | 
				
			|||||||
    <template #suffix>
 | 
					    <template #suffix>
 | 
				
			||||||
      <n-tooltip trigger="hover">
 | 
					      <n-tooltip trigger="hover">
 | 
				
			||||||
        <template #trigger>
 | 
					        <template #trigger>
 | 
				
			||||||
          <c-button circle variant="text" size="small" @click="onCopyClicked">
 | 
					          <c-button circle variant="text" size="small" @click="copy()">
 | 
				
			||||||
            <icon-mdi-content-copy />
 | 
					            <icon-mdi-content-copy />
 | 
				
			||||||
          </c-button>
 | 
					          </c-button>
 | 
				
			||||||
        </template>
 | 
					        </template>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,26 +1,19 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { useClipboard } from '@vueuse/core';
 | 
					import { useCopy } from '@/composable/copy';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = withDefaults(defineProps<{ value?: string }>(), { value: '' });
 | 
					const props = withDefaults(defineProps<{ value?: string }>(), { value: '' });
 | 
				
			||||||
const { value } = toRefs(props);
 | 
					const { value } = toRefs(props);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const initialText = 'Copy to clipboard';
 | 
					const initialText = 'Copy to clipboard';
 | 
				
			||||||
const tooltipText = ref(initialText);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { copy } = useClipboard({ source: value });
 | 
					const { copy, isJustCopied } = useCopy({ source: value, createToast: false });
 | 
				
			||||||
 | 
					const tooltipText = computed(() => isJustCopied.value ? 'Copied!' : initialText);
 | 
				
			||||||
function handleClick() {
 | 
					 | 
				
			||||||
  copy();
 | 
					 | 
				
			||||||
  tooltipText.value = 'Copied!';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  setTimeout(() => (tooltipText.value = initialText), 1000);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <n-tooltip trigger="hover">
 | 
					  <n-tooltip trigger="hover">
 | 
				
			||||||
    <template #trigger>
 | 
					    <template #trigger>
 | 
				
			||||||
      <span class="value" @click="handleClick">{{ value }}</span>
 | 
					      <span class="value" @click="copy()">{{ value }}</span>
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
    {{ tooltipText }}
 | 
					    {{ tooltipText }}
 | 
				
			||||||
  </n-tooltip>
 | 
					  </n-tooltip>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,13 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { Copy } from '@vicons/tabler';
 | 
					import { Copy } from '@vicons/tabler';
 | 
				
			||||||
import { useClipboard, useElementSize } from '@vueuse/core';
 | 
					import { useElementSize } from '@vueuse/core';
 | 
				
			||||||
import hljs from 'highlight.js/lib/core';
 | 
					import hljs from 'highlight.js/lib/core';
 | 
				
			||||||
import jsonHljs from 'highlight.js/lib/languages/json';
 | 
					import jsonHljs from 'highlight.js/lib/languages/json';
 | 
				
			||||||
import sqlHljs from 'highlight.js/lib/languages/sql';
 | 
					import sqlHljs from 'highlight.js/lib/languages/sql';
 | 
				
			||||||
import xmlHljs from 'highlight.js/lib/languages/xml';
 | 
					import xmlHljs from 'highlight.js/lib/languages/xml';
 | 
				
			||||||
import yamlHljs from 'highlight.js/lib/languages/yaml';
 | 
					import yamlHljs from 'highlight.js/lib/languages/yaml';
 | 
				
			||||||
import iniHljs from 'highlight.js/lib/languages/ini';
 | 
					import iniHljs from 'highlight.js/lib/languages/ini';
 | 
				
			||||||
 | 
					import { useCopy } from '@/composable/copy';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = withDefaults(
 | 
					const props = withDefaults(
 | 
				
			||||||
  defineProps<{
 | 
					  defineProps<{
 | 
				
			||||||
@ -33,17 +34,8 @@ hljs.registerLanguage('toml', iniHljs);
 | 
				
			|||||||
const { value, language, followHeightOf, copyPlacement, copyMessage } = toRefs(props);
 | 
					const { value, language, followHeightOf, copyPlacement, copyMessage } = toRefs(props);
 | 
				
			||||||
const { height } = followHeightOf.value ? useElementSize(followHeightOf) : { height: ref(null) };
 | 
					const { height } = followHeightOf.value ? useElementSize(followHeightOf) : { height: ref(null) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { copy } = useClipboard({ source: value });
 | 
					const { copy, isJustCopied } = useCopy({ source: value, createToast: false });
 | 
				
			||||||
const tooltipText = ref(copyMessage.value);
 | 
					const tooltipText = computed(() => isJustCopied.value ? 'Copied!' : copyMessage.value);
 | 
				
			||||||
 | 
					 | 
				
			||||||
function onCopyClicked() {
 | 
					 | 
				
			||||||
  copy();
 | 
					 | 
				
			||||||
  tooltipText.value = 'Copied !';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  setTimeout(() => {
 | 
					 | 
				
			||||||
    tooltipText.value = copyMessage.value;
 | 
					 | 
				
			||||||
  }, 2000);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
@ -61,7 +53,7 @@ function onCopyClicked() {
 | 
				
			|||||||
      <n-tooltip v-if="value" trigger="hover">
 | 
					      <n-tooltip v-if="value" trigger="hover">
 | 
				
			||||||
        <template #trigger>
 | 
					        <template #trigger>
 | 
				
			||||||
          <div class="copy-button" :class="[copyPlacement]">
 | 
					          <div class="copy-button" :class="[copyPlacement]">
 | 
				
			||||||
            <c-button circle important:h-10 important:w-10 @click="onCopyClicked">
 | 
					            <c-button circle important:h-10 important:w-10 @click="copy()">
 | 
				
			||||||
              <n-icon size="22" :component="Copy" />
 | 
					              <n-icon size="22" :component="Copy" />
 | 
				
			||||||
            </c-button>
 | 
					            </c-button>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
@ -70,7 +62,7 @@ function onCopyClicked() {
 | 
				
			|||||||
      </n-tooltip>
 | 
					      </n-tooltip>
 | 
				
			||||||
    </c-card>
 | 
					    </c-card>
 | 
				
			||||||
    <div v-if="copyPlacement === 'outside'" mt-4 flex justify-center>
 | 
					    <div v-if="copyPlacement === 'outside'" mt-4 flex justify-center>
 | 
				
			||||||
      <c-button @click="onCopyClicked">
 | 
					      <c-button @click="copy()">
 | 
				
			||||||
        {{ tooltipText }}
 | 
					        {{ tooltipText }}
 | 
				
			||||||
      </c-button>
 | 
					      </c-button>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +1,19 @@
 | 
				
			|||||||
import { type MaybeRef, get, useClipboard } from '@vueuse/core';
 | 
					// eslint-disable-next-line no-restricted-imports
 | 
				
			||||||
 | 
					import { useClipboard } from '@vueuse/core';
 | 
				
			||||||
import { useMessage } from 'naive-ui';
 | 
					import { useMessage } from 'naive-ui';
 | 
				
			||||||
 | 
					import type { MaybeRefOrGetter } from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function useCopy({ source, text = 'Copied to the clipboard', createToast = true }: { source?: MaybeRefOrGetter<string>; text?: string; createToast?: boolean } = {}) {
 | 
				
			||||||
 | 
					  const { copy, copied, ...rest } = useClipboard({
 | 
				
			||||||
 | 
					    source,
 | 
				
			||||||
 | 
					    legacy: true,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function useCopy({ source, text = 'Copied to the clipboard' }: { source?: MaybeRef<unknown>; text?: string } = {}) {
 | 
					 | 
				
			||||||
  const { copy } = useClipboard(source ? { source: computed(() => String(get(source))) } : {});
 | 
					 | 
				
			||||||
  const message = useMessage();
 | 
					  const message = useMessage();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
 | 
					    ...rest,
 | 
				
			||||||
 | 
					    isJustCopied: copied,
 | 
				
			||||||
    async copy(content?: string, { notificationMessage }: { notificationMessage?: string } = {}) {
 | 
					    async copy(content?: string, { notificationMessage }: { notificationMessage?: string } = {}) {
 | 
				
			||||||
      if (source) {
 | 
					      if (source) {
 | 
				
			||||||
        await copy();
 | 
					        await copy();
 | 
				
			||||||
@ -14,7 +22,9 @@ export function useCopy({ source, text = 'Copied to the clipboard' }: { source?:
 | 
				
			|||||||
        await copy(content);
 | 
					        await copy(content);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      message.success(notificationMessage ?? text);
 | 
					      if (createToast) {
 | 
				
			||||||
 | 
					        message.success(notificationMessage ?? text);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,11 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { Plus, Trash } from '@vicons/tabler';
 | 
					import { Plus, Trash } from '@vicons/tabler';
 | 
				
			||||||
import { useClipboard, useStorage } from '@vueuse/core';
 | 
					import { useStorage } from '@vueuse/core';
 | 
				
			||||||
import _ from 'lodash';
 | 
					import _ from 'lodash';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { arrayToMarkdownTable, computeAverage, computeVariance } from './benchmark-builder.models';
 | 
					import { arrayToMarkdownTable, computeAverage, computeVariance } from './benchmark-builder.models';
 | 
				
			||||||
import DynamicValues from './dynamic-values.vue';
 | 
					import DynamicValues from './dynamic-values.vue';
 | 
				
			||||||
 | 
					import { useCopy } from '@/composable/copy';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const suites = useStorage('benchmark-builder:suites', [
 | 
					const suites = useStorage('benchmark-builder:suites', [
 | 
				
			||||||
  { title: 'Suite 1', data: [5, 10] },
 | 
					  { title: 'Suite 1', data: [5, 10] },
 | 
				
			||||||
@ -47,7 +48,7 @@ const results = computed(() => {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { copy } = useClipboard();
 | 
					const { copy } = useCopy({ createToast: false });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const header = {
 | 
					const header = {
 | 
				
			||||||
  title: 'Suite',
 | 
					  title: 'Suite',
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,7 @@ const getVendorValue = (address: string) => address.trim().replace(/[.:-]/g, '')
 | 
				
			|||||||
const macAddress = ref('20:37:06:12:34:56');
 | 
					const macAddress = ref('20:37:06:12:34:56');
 | 
				
			||||||
const details = computed<string | undefined>(() => db[getVendorValue(macAddress.value)]);
 | 
					const details = computed<string | undefined>(() => db[getVendorValue(macAddress.value)]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { copy } = useCopy({ source: details, text: 'Vendor info copied to the clipboard' });
 | 
					const { copy } = useCopy({ source: () => details.value ?? '', text: 'Vendor info copied to the clipboard' });
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { useClipboard } from '@vueuse/core';
 | 
					import { useCopy } from '@/composable/copy';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = defineProps<{ tokens: { previous: string; current: string; next: string } }>();
 | 
					const props = defineProps<{ tokens: { previous: string; current: string; next: string } }>();
 | 
				
			||||||
const { copy: copyPrevious, copied: previousCopied } = useClipboard();
 | 
					const { copy: copyPrevious, isJustCopied: previousCopied } = useCopy({ createToast: false });
 | 
				
			||||||
const { copy: copyCurrent, copied: currentCopied } = useClipboard();
 | 
					const { copy: copyCurrent, isJustCopied: currentCopied } = useCopy({ createToast: false });
 | 
				
			||||||
const { copy: copyNext, copied: nextCopied } = useClipboard();
 | 
					const { copy: copyNext, isJustCopied: nextCopied } = useCopy({ createToast: false });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { tokens } = toRefs(props);
 | 
					const { tokens } = toRefs(props);
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
				
			|||||||
@ -36,7 +36,7 @@ const validationRoman = useValidation({
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { copy: copyRoman } = useCopy({ source: outputRoman, text: 'Roman number copied to the clipboard' });
 | 
					const { copy: copyRoman } = useCopy({ source: outputRoman, text: 'Roman number copied to the clipboard' });
 | 
				
			||||||
const { copy: copyArabic } = useCopy({ source: outputNumeral, text: 'Arabic number copied to the clipboard' });
 | 
					const { copy: copyArabic } = useCopy({ source: () => String(outputNumeral), text: 'Arabic number copied to the clipboard' });
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
 | 
				
			|||||||
@ -39,7 +39,7 @@ const { copy } = useCopy({ source: obfuscatedString });
 | 
				
			|||||||
        {{ obfuscatedString }}
 | 
					        {{ obfuscatedString }}
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <c-button @click="copy">
 | 
					      <c-button @click="copy()">
 | 
				
			||||||
        <icon-mdi:content-copy />
 | 
					        <icon-mdi:content-copy />
 | 
				
			||||||
      </c-button>
 | 
					      </c-button>
 | 
				
			||||||
    </c-card>
 | 
					    </c-card>
 | 
				
			||||||
 | 
				
			|||||||
@ -34,7 +34,7 @@ const { copy } = useCopy({ source: uuids, text: 'UUIDs copied to the clipboard'
 | 
				
			|||||||
    />
 | 
					    />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div flex justify-center gap-3>
 | 
					    <div flex justify-center gap-3>
 | 
				
			||||||
      <c-button autofocus @click="copy">
 | 
					      <c-button autofocus @click="copy()">
 | 
				
			||||||
        Copy
 | 
					        Copy
 | 
				
			||||||
      </c-button>
 | 
					      </c-button>
 | 
				
			||||||
      <c-button @click="refreshUUIDs">
 | 
					      <c-button @click="refreshUUIDs">
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user