Newer
Older
vmk-ui-kit / src / vue / components / GnProgress.js
/**
 * GnProgress - Linear progress bar and circular step indicator.
 */

import { defineComponent, h, computed } from "vue";
import { cx, iconNode } from "../utils.js";

export default defineComponent({
	name: "GnProgress",
	props: {
		value: { type: Number, default: 0 },
		max: { type: Number, default: 100 },
		variant: { type: String, default: "default" },
		size: { type: String, default: "md" },
		step: { type: Boolean, default: false },
		stepNumber: { type: [String, Number], default: "" },
		state: { type: String, default: "" }
	},
	setup(props, { slots }) {
		const percentage = computed(() => {
			const pct = (props.value / props.max) * 100;
			return Math.max(0, Math.min(100, pct));
		});

		const linearClasses = computed(() => cx("progress", `progress-${props.variant}`, `progress-${props.size}`));

		const stepClasses = computed(() => cx("progress-step", `progress-step-${props.size}`, {
			"is-active": props.state === "active",
			"is-complete": props.state === "complete",
			"is-accent": props.state === "accent"
		}));

		return () => {
			if (props.step) {
				return h("span", { class: stepClasses.value }, [
					props.state === "complete" ? iconNode("ph-check") : (slots.default?.() || props.stepNumber)
				]);
			}

			return h("div", {
				class: linearClasses.value,
				role: "progressbar",
				"aria-valuenow": props.value,
				"aria-valuemin": 0,
				"aria-valuemax": props.max
			}, [
				h("div", {
					class: "progress-bar",
					style: { width: `${percentage.value}%` }
				})
			]);
		};
	}
});