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…
	
		Reference in New Issue
	
	Block a user