var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name2 in all) __defProp(target, name2, { get: all[name2], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var stdin_exports = {}; __export(stdin_exports, { TABS_KEY: () => TABS_KEY, default: () => stdin_default, tabsProps: () => tabsProps }); module.exports = __toCommonJS(stdin_exports); var import_vue = require("vue"); var import_utils = require("../utils"); var import_utils2 = require("./utils"); var import_use = require("@vant/use"); var import_use_id = require("../composables/use-id"); var import_use_route = require("../composables/use-route"); var import_use_refs = require("../composables/use-refs"); var import_use_expose = require("../composables/use-expose"); var import_on_popup_reopen = require("../composables/on-popup-reopen"); var import_use_visibility_change = require("../composables/use-visibility-change"); var import_sticky = require("../sticky"); var import_TabsContent = __toESM(require("./TabsContent")); const [name, bem] = (0, import_utils.createNamespace)("tabs"); const tabsProps = { type: (0, import_utils.makeStringProp)("line"), color: String, border: Boolean, sticky: Boolean, shrink: Boolean, active: (0, import_utils.makeNumericProp)(0), duration: (0, import_utils.makeNumericProp)(0.3), animated: Boolean, ellipsis: import_utils.truthProp, swipeable: Boolean, scrollspy: Boolean, offsetTop: (0, import_utils.makeNumericProp)(0), background: String, lazyRender: import_utils.truthProp, showHeader: import_utils.truthProp, lineWidth: import_utils.numericProp, lineHeight: import_utils.numericProp, beforeChange: Function, swipeThreshold: (0, import_utils.makeNumericProp)(5), titleActiveColor: String, titleInactiveColor: String }; const TABS_KEY = Symbol(name); var stdin_default = (0, import_vue.defineComponent)({ name, props: tabsProps, emits: ["change", "scroll", "rendered", "clickTab", "update:active"], setup(props, { emit, slots }) { let tabHeight; let lockScroll; let stickyFixed; let cancelScrollLeftToRaf; let cancelScrollTopToRaf; const root = (0, import_vue.ref)(); const navRef = (0, import_vue.ref)(); const wrapRef = (0, import_vue.ref)(); const contentRef = (0, import_vue.ref)(); const id = (0, import_use_id.useId)(); const scroller = (0, import_use.useScrollParent)(root); const [titleRefs, setTitleRefs] = (0, import_use_refs.useRefs)(); const { children, linkChildren } = (0, import_use.useChildren)(TABS_KEY); const state = (0, import_vue.reactive)({ inited: false, position: "", lineStyle: {}, currentIndex: -1 }); const scrollable = (0, import_vue.computed)(() => children.length > +props.swipeThreshold || !props.ellipsis || props.shrink); const navStyle = (0, import_vue.computed)(() => ({ borderColor: props.color, background: props.background })); const getTabName = (tab, index) => { var _a; return (_a = tab.name) != null ? _a : index; }; const currentName = (0, import_vue.computed)(() => { const activeTab = children[state.currentIndex]; if (activeTab) { return getTabName(activeTab, state.currentIndex); } }); const offsetTopPx = (0, import_vue.computed)(() => (0, import_utils.unitToPx)(props.offsetTop)); const scrollOffset = (0, import_vue.computed)(() => { if (props.sticky) { return offsetTopPx.value + tabHeight; } return 0; }); const scrollIntoView = (immediate) => { const nav = navRef.value; const titles = titleRefs.value; if (!scrollable.value || !nav || !titles || !titles[state.currentIndex]) { return; } const title = titles[state.currentIndex].$el; const to = title.offsetLeft - (nav.offsetWidth - title.offsetWidth) / 2; if (cancelScrollLeftToRaf) cancelScrollLeftToRaf(); cancelScrollLeftToRaf = (0, import_utils2.scrollLeftTo)(nav, to, immediate ? 0 : +props.duration); }; const setLine = () => { const shouldAnimate = state.inited; (0, import_vue.nextTick)(() => { const titles = titleRefs.value; if (!titles || !titles[state.currentIndex] || props.type !== "line" || (0, import_utils.isHidden)(root.value)) { return; } const title = titles[state.currentIndex].$el; const { lineWidth, lineHeight } = props; const left = title.offsetLeft + title.offsetWidth / 2; const lineStyle = { width: (0, import_utils.addUnit)(lineWidth), backgroundColor: props.color, transform: `translateX(${left}px) translateX(-50%)` }; if (shouldAnimate) { lineStyle.transitionDuration = `${props.duration}s`; } if ((0, import_utils.isDef)(lineHeight)) { const height = (0, import_utils.addUnit)(lineHeight); lineStyle.height = height; lineStyle.borderRadius = height; } state.lineStyle = lineStyle; }); }; const findAvailableTab = (index) => { const diff = index < state.currentIndex ? -1 : 1; while (index >= 0 && index < children.length) { if (!children[index].disabled) { return index; } index += diff; } }; const setCurrentIndex = (currentIndex, skipScrollIntoView) => { const newIndex = findAvailableTab(currentIndex); if (!(0, import_utils.isDef)(newIndex)) { return; } const newTab = children[newIndex]; const newName = getTabName(newTab, newIndex); const shouldEmitChange = state.currentIndex !== null; if (state.currentIndex !== newIndex) { state.currentIndex = newIndex; if (!skipScrollIntoView) { scrollIntoView(); } setLine(); } if (newName !== props.active) { emit("update:active", newName); if (shouldEmitChange) { emit("change", newName, newTab.title); } } if (stickyFixed && !props.scrollspy) { (0, import_utils.setRootScrollTop)(Math.ceil((0, import_utils.getElementTop)(root.value) - offsetTopPx.value)); } }; const setCurrentIndexByName = (name2, skipScrollIntoView) => { const matched = children.find((tab, index2) => getTabName(tab, index2) === name2); const index = matched ? children.indexOf(matched) : 0; setCurrentIndex(index, skipScrollIntoView); }; const scrollToCurrentContent = (immediate = false) => { if (props.scrollspy) { const target = children[state.currentIndex].$el; if (target && scroller.value) { const to = (0, import_utils.getElementTop)(target, scroller.value) - scrollOffset.value; lockScroll = true; if (cancelScrollTopToRaf) cancelScrollTopToRaf(); cancelScrollTopToRaf = (0, import_utils2.scrollTopTo)(scroller.value, to, immediate ? 0 : +props.duration, () => { lockScroll = false; }); } } }; const onClickTab = (item, index, event) => { const { title, disabled } = children[index]; const name2 = getTabName(children[index], index); if (!disabled) { (0, import_utils.callInterceptor)(props.beforeChange, { args: [name2], done: () => { setCurrentIndex(index); scrollToCurrentContent(); } }); (0, import_use_route.route)(item); } emit("clickTab", { name: name2, title, event, disabled }); }; const onStickyScroll = (params) => { stickyFixed = params.isFixed; emit("scroll", params); }; const scrollTo = (name2) => { (0, import_vue.nextTick)(() => { setCurrentIndexByName(name2); scrollToCurrentContent(true); }); }; const getCurrentIndexOnScroll = () => { for (let index = 0; index < children.length; index++) { const { top } = (0, import_use.useRect)(children[index].$el); if (top > scrollOffset.value) { return index === 0 ? 0 : index - 1; } } return children.length - 1; }; const onScroll = () => { if (props.scrollspy && !lockScroll) { const index = getCurrentIndexOnScroll(); setCurrentIndex(index); } }; const renderLine = () => { if (props.type === "line" && children.length) { return (0, import_vue.createVNode)("div", { "class": bem("line"), "style": state.lineStyle }, null); } }; const renderHeader = () => { var _a, _b, _c; const { type, border, sticky } = props; const Header = [(0, import_vue.createVNode)("div", { "ref": sticky ? void 0 : wrapRef, "class": [bem("wrap"), { [import_utils.BORDER_TOP_BOTTOM]: type === "line" && border }] }, [(0, import_vue.createVNode)("div", { "ref": navRef, "role": "tablist", "class": bem("nav", [type, { shrink: props.shrink, complete: scrollable.value }]), "style": navStyle.value, "aria-orientation": "horizontal" }, [(_a = slots["nav-left"]) == null ? void 0 : _a.call(slots), children.map((item) => item.renderTitle(onClickTab)), renderLine(), (_b = slots["nav-right"]) == null ? void 0 : _b.call(slots)])]), (_c = slots["nav-bottom"]) == null ? void 0 : _c.call(slots)]; if (sticky) { return (0, import_vue.createVNode)("div", { "ref": wrapRef }, [Header]); } return Header; }; const resize = () => { setLine(); (0, import_vue.nextTick)(() => { var _a, _b; scrollIntoView(true); (_b = (_a = contentRef.value) == null ? void 0 : _a.swipeRef.value) == null ? void 0 : _b.resize(); }); }; (0, import_vue.watch)(() => [props.color, props.duration, props.lineWidth, props.lineHeight], setLine); (0, import_vue.watch)(import_utils.windowWidth, resize); (0, import_vue.watch)(() => props.active, (value) => { if (value !== currentName.value) { setCurrentIndexByName(value); } }); (0, import_vue.watch)(() => children.length, () => { if (state.inited) { setCurrentIndexByName(props.active); setLine(); (0, import_vue.nextTick)(() => { scrollIntoView(true); }); } }); const init = () => { setCurrentIndexByName(props.active, true); (0, import_vue.nextTick)(() => { state.inited = true; if (wrapRef.value) { tabHeight = (0, import_use.useRect)(wrapRef.value).height; } scrollIntoView(true); }); }; const onRendered = (name2, title) => emit("rendered", name2, title); (0, import_use_expose.useExpose)({ resize, scrollTo }); (0, import_vue.onActivated)(setLine); (0, import_on_popup_reopen.onPopupReopen)(setLine); (0, import_use.onMountedOrActivated)(init); (0, import_use_visibility_change.useVisibilityChange)(root, setLine); (0, import_use.useEventListener)("scroll", onScroll, { target: scroller, passive: true }); linkChildren({ id, props, setLine, scrollable, onRendered, currentName, setTitleRefs, scrollIntoView }); return () => (0, import_vue.createVNode)("div", { "ref": root, "class": bem([props.type]) }, [props.showHeader ? props.sticky ? (0, import_vue.createVNode)(import_sticky.Sticky, { "container": root.value, "offsetTop": offsetTopPx.value, "onScroll": onStickyScroll }, { default: () => [renderHeader()] }) : renderHeader() : null, (0, import_vue.createVNode)(import_TabsContent.default, { "ref": contentRef, "count": children.length, "inited": state.inited, "animated": props.animated, "duration": props.duration, "swipeable": props.swipeable, "lazyRender": props.lazyRender, "currentIndex": state.currentIndex, "onChange": setCurrentIndex }, { default: () => { var _a; return [(_a = slots.default) == null ? void 0 : _a.call(slots)]; } })]); } });