Newer
Older
gnexus-ui-kit / src / vue / components / GnCopyButton.js
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: null }
	},
	emits: ["copy"],
	setup(props, { emit }) {
		const copied = ref(false);
		let timer = null;

		const copy = async () => {
			try {
				await navigator.clipboard.writeText(props.text);
			} catch {
				// Fallback for older browsers or non-secure contexts
				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)]);
	}
});