Skip to content
Snippets Groups Projects
Unverified Commit c0f628b2 authored by Mateusz Tyszczak's avatar Mateusz Tyszczak :scroll:
Browse files

Add copy event to classic button component

parent 44ff025c
No related branches found
No related tags found
No related merge requests found
Pipeline #118010 passed
......@@ -142,9 +142,6 @@ onMounted(() => {
void connect(false);
});
const copyContent = (content: string) => {
navigator.clipboard.writeText(String(content));
};
const generateAccountUpdateTransaction = async(): Promise<string> => {
const wax = await getWax();
const tx = await wax.createTransaction();
......@@ -251,12 +248,12 @@ const updateAccountName = (value: string | any) => {
</div>
</div>
<div class="flex items-center flex-col">
<Button :disabled="isLoading" @click="copyContent(getAuthorityUpdateSigningLink())" variant="outline" size="lg" class="mt-4 px-8 py-4 border-[#FF5C16] border-[1px]">
<Button :disabled="isLoading" :copy="getAuthorityUpdateSigningLink" variant="outline" size="lg" class="mt-4 px-8 py-4 border-[#FF5C16] border-[1px]">
<span class="text-md font-bold">Copy signing link</span>
</Button>
<Separator label="Or" class="mt-8" />
<div class="flex justify-center mt-4">
<Button :disabled="isLoading" @click="generateAccountUpdateTransaction()" variant="outline" size="lg" class="px-8 opacity-[0.9] py-4 border-[#FF5C16] border-[1px]">
<Button :disabled="isLoading" :copy="generateAccountUpdateTransaction" variant="outline" size="lg" class="px-8 opacity-[0.9] py-4 border-[#FF5C16] border-[1px]">
<span class="text-md font-bold">Copy entire transaction</span>
</Button>
</div>
......@@ -277,7 +274,7 @@ const updateAccountName = (value: string | any) => {
</div>
</div>
<div class="flex items-center flex-col">
<Button :disabled="isLoading" @click="copyContent(getAccountCreateSigningLink())" variant="outline" size="lg" class="mt-4 px-8 py-4 border-[#FF5C16] border-[1px]">
<Button :copy="getAccountCreateSigningLink" :disabled="isLoading" variant="outline" size="lg" class="mt-4 px-8 py-4 border-[#FF5C16] border-[1px]">
<span class="text-md font-bold">Copy signing link</span>
</Button>
</div>
......
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { ref, type HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import { Primitive, type PrimitiveProps } from 'reka-ui'
import { type ButtonVariants, buttonVariants } from '.'
import { mdiLoading } from '@mdi/js'
import { mdiCheck, mdiLoading } from '@mdi/js'
import { copyText } from '@/utils/copy'
interface Props extends PrimitiveProps {
variant?: ButtonVariants['variant']
......@@ -11,12 +12,31 @@ interface Props extends PrimitiveProps {
class?: HTMLAttributes['class']
loading?: boolean
disabled?: boolean
copy?: string | (() => (string | Promise<string>))
}
const props = withDefaults(defineProps<Props>(), {
as: 'button',
loading: false
})
const copyLoading = ref(false);
const copyBtn = () => {
if (!props.copy) return;
const text = typeof props.copy === 'function' ? props.copy() : props.copy;
if(text instanceof Promise)
text.then((text) => {
copyText(text);
});
else
copyText(text);
copyLoading.value = true;
setTimeout(() => {
copyLoading.value = false;
}, 1000);
};
</script>
<template>
......@@ -25,13 +45,19 @@ const props = withDefaults(defineProps<Props>(), {
:as-child="asChild"
:disabled="loading || disabled"
:class="[ cn(buttonVariants({ variant, size }), props.class)]"
@click="copyBtn"
>
<span v-if="copy && copyLoading" class="absolute mx-auto">
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path :style="{
fill: !variant || variant === 'default' ? 'hsl(var(--background))' : 'hsl(var(--foreground))'
}" :d="mdiCheck"/></svg>
</span>
<span v-if="loading" class="animate-spin absolute mx-auto">
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path :style="{
fill: !variant || variant === 'default' ? 'hsl(var(--background))' : 'hsl(var(--foreground))'
}" :d="mdiLoading"/></svg>
</span>
<span :style="{ 'visibility': loading ? 'hidden' : 'visible' }" class="inline-flex items-center justify-center gap-2">
<span :style="{ 'visibility': loading || copyLoading ? 'hidden' : 'visible' }" class="inline-flex items-center justify-center gap-2">
<slot/>
</span>
</Primitive>
......
......@@ -4,6 +4,7 @@ import { cn } from '@/lib/utils'
import { Primitive, type PrimitiveProps } from 'reka-ui'
import { buttonVariants } from '.'
import { mdiCheck, mdiContentCopy } from '@mdi/js'
import { copyText } from '@/utils/copy'
interface Props extends PrimitiveProps {
class?: HTMLAttributes['class'];
......@@ -18,7 +19,7 @@ const copyBtn = (event: MouseEvent) => {
const target = event.target as HTMLElement;
const value = target.getAttribute("data-copy");
if (!value) return;
navigator.clipboard.writeText(String(value));
copyText(value);
const oldAttribute = target.children[0].children[0].getAttribute('d');
target.children[0].children[0].setAttribute('d', mdiCheck);
......
/**
* Copies given text into clipboard.
*
* This function supports 3 ways of copying and fallbacks if any of them fails:
* 1. Using the modern Clipboard API (navigator.clipboard.writeText) - on most browsers works only in secure context (HTTPS) or localhost
* 2. Using the deprecated document.execCommand("copy") - deprecated, but still supported by most browsers - with Firefox works only on "click" event triggered by the user
* 3. Using the prompt function - the most universal way, but requires user interaction
*/
export const copyText = (text: string) => {
try {
if (navigator.clipboard) { // is secure context
return navigator.clipboard.writeText(text).catch(() => {
prompt("Copy to clipboard: Ctrl+C, Enter", text);
});
} else if (document.queryCommandSupported && document.queryCommandSupported("copy")) { // check if we can use deprecated copy command
const textarea = document.createElement("textarea");
textarea.textContent = text;
textarea.style.width = "0";
textarea.style.height = "0";
textarea.style.position = "fixed"; // Prevent scrolling to bottom of page in MS Edge.
document.body.appendChild(textarea);
textarea.select();
try {
if(!document.execCommand("copy")) // Security exception may be thrown by some browsers.
throw new Error("Copy command was unsuccessful");
} finally {
document.body.removeChild(textarea);
}
}
throw new Error("No clipboard support");
} catch {
prompt("Copy to clipboard: Ctrl+C, Enter", text);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment