56 lines
1.5 KiB
Vue
56 lines
1.5 KiB
Vue
<template>
|
|
<v-btn
|
|
:color="copied ? 'success' : color"
|
|
:variant="variant"
|
|
:icon="iconOnly"
|
|
:size="iconOnly ? 'x-small' : 'default'"
|
|
@click="handleCopy"
|
|
>
|
|
<v-icon :start="!iconOnly" :icon="copied ? 'mdi-check' : 'mdi-content-copy'" />
|
|
<template v-if="!iconOnly">{{ copied ? 'Copied Link To Page!' : label }}</template>
|
|
<v-tooltip v-if="iconOnly" activator="parent" location="top">
|
|
{{ copied ? 'Copied Link To Page!' : label }}
|
|
</v-tooltip>
|
|
</v-btn>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref } from 'vue';
|
|
import { useDisplay } from 'vuetify';
|
|
import { copyToClipboard } from '@/Composables/useClipboard';
|
|
|
|
interface Props {
|
|
label?: string;
|
|
color?: string;
|
|
variant?: 'flat' | 'text' | 'elevated' | 'tonal' | 'outlined' | 'plain';
|
|
resetDelay?: number;
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
label: 'Copy link',
|
|
color: 'primary',
|
|
variant: 'outlined',
|
|
resetDelay: 2000,
|
|
});
|
|
|
|
const { mobile } = useDisplay();
|
|
const iconOnly = mobile;
|
|
|
|
const copied = ref(false);
|
|
let resetTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
|
|
async function handleCopy() {
|
|
try {
|
|
await copyToClipboard(window.location.href);
|
|
copied.value = true;
|
|
|
|
if (resetTimeout) clearTimeout(resetTimeout);
|
|
resetTimeout = setTimeout(() => {
|
|
copied.value = false;
|
|
}, props.resetDelay);
|
|
} catch (err) {
|
|
console.error('Failed to copy URL:', err);
|
|
}
|
|
}
|
|
</script>
|