components/markdown/CodeBlockCopyClipboard.vue (102 lines of code) (raw):
<template>
<div class="clipboard" ref="copyButton">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
v-if="clipboardChecked"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"
/>
</svg>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
v-else
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3"
/>
</svg>
</svg>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref } from '@vue/composition-api'
import Clipboard from 'clipboard'
export default defineComponent({
components: {},
props: {
source: {
type: String
}
},
setup(props) {
const copyButton = ref<HTMLElement | null>(null)
const clipboardChecked = ref(false)
onMounted(() => {
const copyCode = new Clipboard(copyButton.value!, {
text(trigger) {
return props.source!
}
})
copyCode.on('success', event => {
event.clearSelection()
clipboardChecked.value = true
window.setTimeout(() => {
clipboardChecked.value = false
}, 2000)
})
})
return {
clipboardChecked,
copyButton
}
}
})
</script>
<style lang="postcss" scoped>
.clipboard {
position: absolute;
right: 0;
bottom: 0;
@apply text-blue-gray-400;
@apply mr-7 mb-3;
@apply rounded-lg border-blue-gray-400 border;
@apply p-2;
@apply cursor-pointer;
&:hover {
@apply bg-blue-gray-400 bg-opacity-25;
}
width: 30px;
height: 30px;
svg {
width: 100%;
height: 100%;
}
}
&:hover {
.clipboard {
@apply block;
}
}
</style>