Newer
Older
gnexus-ui-kit / src / vue / components / GnToastProvider.js
@Eugene Sukhodolskiy Eugene Sukhodolskiy 15 hours ago 2 KB Add Vue adapter foundation
import { defineComponent, h, provide, ref } from "vue";
import { cx, iconNode, normalizeVariant } from "../utils.js";
import { toastKey } from "../composables/toast-context.js";

const iconByVariant = {
	info: "ph-info",
	success: "ph-check-circle",
	warning: "ph-warning",
	danger: "ph-warning-octagon",
	error: "ph-warning-octagon",
	primary: "ph-info",
	secondary: "ph-info"
};

export default defineComponent({
	name: "GnToastProvider",
	props: {
		lifetime: { type: Number, default: 4000 }
	},
	setup(props, { slots, expose }) {
		const toast = ref(null);
		let timer = null;

		const close = () => {
			toast.value = null;
			window.clearTimeout(timer);
			timer = null;
		};

		const show = options => {
			const variant = normalizeVariant(options.variant || options.type || "info", "info");
			toast.value = {
				id: Date.now(),
				variant: variant === "error" ? "danger" : variant,
				title: options.title || "",
				text: options.text || options.message || "",
				icon: options.icon || iconByVariant[variant] || iconByVariant.info
			};

			window.clearTimeout(timer);

			if(options.lifetime !== 0) {
				timer = window.setTimeout(close, options.lifetime || props.lifetime);
			}
		};

		const api = {
			show,
			close,
			info: options => show({ ...options, variant: "info" }),
			success: options => show({ ...options, variant: "success" }),
			warning: options => show({ ...options, variant: "warning" }),
			danger: options => show({ ...options, variant: "danger" }),
			error: options => show({ ...options, variant: "danger" })
		};

		provide(toastKey, api);
		expose(api);

		return () => [
			slots.default?.(),
			toast.value && h("div", {
				class: cx("toast a-show", `toast-${toast.value.variant}`),
				role: "alert"
			}, [
				h("div", { class: "toast-content" }, [
					h("h4", { class: "toast-title" }, [
						iconNode(toast.value.icon),
						toast.value.title
					]),
					h("p", { class: "toast-text" }, toast.value.text)
				]),
				h("button", {
					class: "btn-icon toast-close",
					type: "button",
					"aria-label": "Close",
					onClick: close
				}, [iconNode("ph-x")])
			])
		];
	}
});