UNPKG

maz-ui

Version:

A standalone components library for Vue.Js 3 & Nuxt.Js 3

139 lines (138 loc) 6.46 kB
import { defineComponent, defineAsyncComponent, ref, computed, onBeforeMount, onMounted, watch, createElementBlock, openBlock, normalizeClass, createElementVNode, normalizeStyle, Fragment, renderList, renderSlot, createTextVNode, createBlock, createCommentVNode, toDisplayString, unref, mergeProps, withCtx } from "vue"; import { s as sleep } from "../chunks/sleep.BLRH1qZG.js"; import { useInjectStrict } from "../composables/useInjectStrict.js"; import { _ as _export_sfc } from "../chunks/_plugin-vue_export-helper.B--vMWp3.js"; import '../assets/MazTabsBar.BRr1XiYu.css';const _hoisted_1 = ["disabled", "onClick"], _sfc_main = /* @__PURE__ */ defineComponent({ __name: "MazTabsBar", props: { items: {}, persistent: { type: Boolean, default: !1 }, queryParam: { default: "tab" }, block: { type: Boolean, default: !1 }, elevation: { type: Boolean, default: !1 }, autoScroll: { type: Boolean, default: !0 }, bordered: { type: Boolean, default: !0 } }, setup(__props) { const MazBadge = defineAsyncComponent(() => import("./MazBadge.js")), { currentTab, updateCurrentTab } = useInjectStrict("maz-tabs"); function selectTab(tabIndex) { updateCurrentTab(tabIndex + 1), __props.persistent && addOrUpdateQueryParamTab(tabIndex + 1); } const tabsBarRef = ref(), itemRefs = ref([]); function isActiveTab(index) { return currentTab.value === index + 1; } function addElementToItemRefs({ mazBtn, index }) { itemRefs.value[index] = mazBtn && "$el" in mazBtn ? mazBtn.$el : mazBtn; } const normalizedItems = computed( () => __props.items.map((item) => ({ label: typeof item == "string" ? item : item.label, disabled: typeof item == "string" ? !1 : item.disabled ?? !1, badge: typeof item == "string" ? void 0 : item.badge })) ), tabsIndicatorState = ref(), tabsBarHasScrollAnimation = ref(!1); async function setIndicatorAndScroll() { if (!__props.autoScroll) return; await sleep(150); const tabsBar = tabsBarRef.value, activeTab = itemRefs.value[currentTab.value - 1]; if (!tabsBar || !activeTab) return; const scrollOffset = 50; if (activeTab.offsetLeft - scrollOffset < tabsBar.scrollLeft || activeTab.offsetLeft + activeTab.offsetWidth > tabsBar.scrollLeft + tabsBar.clientWidth) { const tabBarPaddingLeft = globalThis.getComputedStyle(tabsBar, "padding-left").paddingLeft, tabsBarPaddingOffset = Number(tabBarPaddingLeft.slice(0, -2)); tabsBar.scrollTo({ left: activeTab.offsetLeft - tabsBarPaddingOffset - scrollOffset, behavior: tabsBarHasScrollAnimation.value ? "smooth" : "instant" }); } if (typeof currentTab.value != "number") return; const indicatorWidth = activeTab?.offsetWidth ?? 0, indicatorHeight = activeTab?.offsetHeight ?? 0, translateXValue = activeTab?.offsetLeft ?? 0; tabsIndicatorState.value = { transform: `translateX(${translateXValue}px)`, width: `${indicatorWidth}px`, height: `${indicatorHeight}px` }, tabsBarHasScrollAnimation.value = !0; } function getTabStyle(index, disabled) { return disabled ? {} : currentTab.value === index + 1 ? "color: hsl(var(--maz-foreground))" : "color: hsl(var(--maz-muted))"; } onBeforeMount(() => { (currentTab.value < 1 || currentTab.value > normalizedItems.value.length) && console.error( `[maz-ui](MazTabsBar) The model-value should be between 1 and ${normalizedItems.value.length}` ); }), onMounted(() => { (__props.persistent || currentTab.value) && setIndicatorAndScroll(); }), watch( () => [currentTab.value, normalizedItems.value], () => { setIndicatorAndScroll(); } ); function getQueryParamTab() { const urlActuelle = new URL(globalThis.location.href); return Number(urlActuelle.searchParams.get(__props.queryParam)); } function addOrUpdateQueryParamTab(tab) { const urlActuelle = new URL(globalThis.location.href); urlActuelle.searchParams.set(__props.queryParam, String(tab)), globalThis.history.replaceState({}, document.title, urlActuelle.toString()); } return onMounted(() => { __props.persistent && updateCurrentTab(getQueryParamTab() || currentTab.value || 1); }), (_ctx, _cache) => (openBlock(), createElementBlock("div", { ref_key: "tabsBarRef", ref: tabsBarRef, class: normalizeClass(["m-tabs-bar m-reset-css", { "--block": __props.block, "--elevation": __props.elevation, "--bordered": __props.bordered }]) }, [ createElementVNode("div", { class: normalizeClass(["m-tabs-bar__indicator", { "--animated": tabsBarHasScrollAnimation.value }]), style: normalizeStyle([tabsIndicatorState.value]) }, null, 6), (openBlock(!0), createElementBlock(Fragment, null, renderList(normalizedItems.value, (item, index) => (openBlock(), createElementBlock("button", { key: index, ref_for: !0, ref: (mazBtn) => addElementToItemRefs({ mazBtn, index }), class: normalizeClass([{ "--active": isActiveTab(index), "--disabled": item.disabled }, "m-tabs-bar__item"]), disabled: item.disabled, style: normalizeStyle(getTabStyle(index, item.disabled)), onClick: ($event) => item.disabled ? void 0 : selectTab(index) }, [ renderSlot(_ctx.$slots, "item", { item, active: isActiveTab(index), index }, () => [ createTextVNode(toDisplayString(item.label) + " ", 1), item.badge ? (openBlock(), createBlock(unref(MazBadge), mergeProps({ key: 0, ref_for: !0 }, item.badge, { size: item.badge.size ?? "0.7rem", class: "m-tabs-bar__item__badge" }), { default: withCtx(() => [ renderSlot(_ctx.$slots, "badge-content", { content: item.badge.content }, () => [ createTextVNode(toDisplayString(item.badge.content), 1) ], !0) ]), _: 2 }, 1040, ["size"])) : createCommentVNode("", !0) ], !0) ], 14, _hoisted_1))), 128)) ], 2)); } }), MazTabsBar = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-a10056dd"]]); export { MazTabsBar as default };