/**
* GnCopyButton - Copies text to the clipboard and shows a transient success state.
*
* @typedef {Object} GnCopyButtonProps
* @property {string} text - Text to copy
* @property {string} [icon='ph-copy'] - Default icon name
* @property {string} [successIcon='ph-check'] - Icon shown after copying
* @property {number} [duration=3000] - How long the success state lasts (ms)
* @property {string} [label='Copy'] - Accessible label
* @property {string} [size=''] - "sm" for a smaller button
*
* @emits copy
*/
import { defineComponent, h, ref } from "vue";
import { cx, iconNode } from "../utils.js";
export default defineComponent({
name: "GnCopyButton",
props: {
text: { type: String, required: true },
icon: { type: String, default: "ph-copy" },
successIcon: { type: String, default: "ph-check" },
duration: { type: Number, default: 3000 },
label: { type: String, default: "Copy" },
size: { type: String, default: "" }
},
emits: ["copy"],
setup(props, { emit }) {
const copied = ref(false);
let timer = null;
const copy = async () => {
try {
await navigator.clipboard.writeText(props.text);
} catch {
const textarea = document.createElement("textarea");
textarea.value = props.text;
textarea.style.position = "fixed";
textarea.style.opacity = "0";
document.body.appendChild(textarea);
textarea.select();
document.execCommand("copy");
document.body.removeChild(textarea);
}
copied.value = true;
window.clearTimeout(timer);
timer = window.setTimeout(() => {
copied.value = false;
}, props.duration);
emit("copy", props.text);
};
return () => h("button", {
class: cx("btn-icon", { "btn-icon-sm": props.size === "sm" }),
type: "button",
"aria-label": props.label,
onClick: copy
}, [iconNode(copied.value ? props.successIcon : props.icon)]);
}
});