"use strict"; exports.__esModule = true; exports["default"] = void 0; var _utils = require("../utils"); var _raf = require("../utils/raf"); var _event = require("../utils/event"); var _touch = require("../mixins/touch"); var _scroll = require("../utils/scroll"); var _use = (0, _utils.use)('tabs'), sfc = _use[0], bem = _use[1]; var tabBem = (0, _utils.use)('tab')[1]; var _default = sfc({ mixins: [_touch.TouchMixin], model: { prop: 'active' }, props: { color: String, sticky: Boolean, animated: Boolean, offsetTop: Number, swipeable: Boolean, background: String, titleActiveColor: String, titleInactiveColor: String, ellipsis: { type: Boolean, "default": true }, lazyRender: { type: Boolean, "default": true }, lineWidth: { type: Number, "default": null }, lineHeight: { type: Number, "default": null }, active: { type: [Number, String], "default": 0 }, type: { type: String, "default": 'line' }, duration: { type: Number, "default": 0.3 }, swipeThreshold: { type: Number, "default": 4 } }, data: function data() { return { tabs: [], position: '', curActive: null, lineStyle: { backgroundColor: this.color }, events: { resize: false, sticky: false, swipeable: false } }; }, computed: { // whether the nav is scrollable scrollable: function scrollable() { return this.tabs.length > this.swipeThreshold || !this.ellipsis; }, wrapStyle: function wrapStyle() { switch (this.position) { case 'top': return { top: this.offsetTop + 'px', position: 'fixed' }; case 'bottom': return { top: 'auto', bottom: 0 }; default: return null; } }, navStyle: function navStyle() { return { borderColor: this.color, background: this.background }; }, trackStyle: function trackStyle() { if (this.animated) { return { left: -1 * this.curActive * 100 + "%", transitionDuration: this.duration + "s" }; } } }, watch: { active: function active(val) { if (val !== this.curActive) { this.correctActive(val); } }, color: function color() { this.setLine(); }, tabs: function tabs() { this.correctActive(this.curActive || this.active); this.scrollIntoView(); this.setLine(); }, curActive: function curActive() { this.scrollIntoView(); this.setLine(); // scroll to correct position if (this.position === 'top' || this.position === 'bottom') { (0, _scroll.setScrollTop)(window, (0, _scroll.getElementTop)(this.$el) - this.offsetTop); } }, sticky: function sticky() { this.handlers(true); }, swipeable: function swipeable() { this.handlers(true); } }, mounted: function mounted() { this.onShow(); }, activated: function activated() { this.onShow(); this.setLine(); }, deactivated: function deactivated() { this.handlers(false); }, beforeDestroy: function beforeDestroy() { this.handlers(false); }, methods: { onShow: function onShow() { var _this = this; this.$nextTick(function () { _this.inited = true; _this.handlers(true); _this.scrollIntoView(true); }); }, // whether to bind sticky listener handlers: function handlers(bind) { var events = this.events; var sticky = this.sticky && bind; var swipeable = this.swipeable && bind; // listen to window resize event if (events.resize !== bind) { events.resize = bind; (bind ? _event.on : _event.off)(window, 'resize', this.setLine, true); } // listen to scroll event if (events.sticky !== sticky) { events.sticky = sticky; this.scrollEl = this.scrollEl || (0, _scroll.getScrollEventTarget)(this.$el); (sticky ? _event.on : _event.off)(this.scrollEl, 'scroll', this.onScroll, true); this.onScroll(); } // listen to touch event if (events.swipeable !== swipeable) { events.swipeable = swipeable; var content = this.$refs.content; var action = swipeable ? _event.on : _event.off; action(content, 'touchstart', this.touchStart); action(content, 'touchmove', this.touchMove); action(content, 'touchend', this.onTouchEnd); action(content, 'touchcancel', this.onTouchEnd); } }, // watch swipe touch end onTouchEnd: function onTouchEnd() { var direction = this.direction, deltaX = this.deltaX, curActive = this.curActive; var minSwipeDistance = 50; /* istanbul ignore else */ if (direction === 'horizontal' && this.offsetX >= minSwipeDistance) { /* istanbul ignore else */ if (deltaX > 0 && curActive !== 0) { this.setCurActive(curActive - 1); } else if (deltaX < 0 && curActive !== this.tabs.length - 1) { this.setCurActive(curActive + 1); } } }, // adjust tab position onScroll: function onScroll() { var scrollTop = (0, _scroll.getScrollTop)(window) + this.offsetTop; var elTopToPageTop = (0, _scroll.getElementTop)(this.$el); var elBottomToPageTop = elTopToPageTop + this.$el.offsetHeight - this.$refs.wrap.offsetHeight; if (scrollTop > elBottomToPageTop) { this.position = 'bottom'; } else if (scrollTop > elTopToPageTop) { this.position = 'top'; } else { this.position = ''; } var scrollParams = { scrollTop: scrollTop, isFixed: this.position === 'top' }; this.$emit('scroll', scrollParams); }, // update nav bar style setLine: function setLine() { var _this2 = this; var shouldAnimate = this.inited; this.$nextTick(function () { var tabs = _this2.$refs.tabs; if (!tabs || !tabs[_this2.curActive] || _this2.type !== 'line') { return; } var tab = tabs[_this2.curActive]; var lineWidth = _this2.lineWidth, lineHeight = _this2.lineHeight; var width = (0, _utils.isDef)(lineWidth) ? lineWidth : tab.offsetWidth / 2; var left = tab.offsetLeft + (tab.offsetWidth - width) / 2; var lineStyle = { width: width + "px", backgroundColor: _this2.color, transform: "translateX(" + left + "px)" }; if (shouldAnimate) { lineStyle.transitionDuration = _this2.duration + "s"; } if ((0, _utils.isDef)(lineHeight)) { var height = lineHeight + "px"; lineStyle.height = height; lineStyle.borderRadius = height; } _this2.lineStyle = lineStyle; }); }, // correct the value of active correctActive: function correctActive(active) { active = +active; var exist = this.tabs.some(function (tab) { return tab.index === active; }); var defaultActive = (this.tabs[0] || {}).index || 0; this.setCurActive(exist ? active : defaultActive); }, setCurActive: function setCurActive(active) { active = this.findAvailableTab(active, active < this.curActive); if ((0, _utils.isDef)(active) && active !== this.curActive) { this.$emit('input', active); if (this.curActive !== null) { this.$emit('change', active, this.tabs[active].title); } this.curActive = active; } }, findAvailableTab: function findAvailableTab(active, reverse) { var diff = reverse ? -1 : 1; var index = active; while (index >= 0 && index < this.tabs.length) { if (!this.tabs[index].disabled) { return index; } index += diff; } }, // emit event when clicked onClick: function onClick(index) { var _this$tabs$index = this.tabs[index], title = _this$tabs$index.title, disabled = _this$tabs$index.disabled; if (disabled) { this.$emit('disabled', index, title); } else { this.setCurActive(index); this.$emit('click', index, title); } }, // scroll active tab into view scrollIntoView: function scrollIntoView(immediate) { var tabs = this.$refs.tabs; if (!this.scrollable || !tabs || !tabs[this.curActive]) { return; } var nav = this.$refs.nav; var scrollLeft = nav.scrollLeft, navWidth = nav.offsetWidth; var _tabs$this$curActive = tabs[this.curActive], offsetLeft = _tabs$this$curActive.offsetLeft, tabWidth = _tabs$this$curActive.offsetWidth; this.scrollTo(nav, scrollLeft, offsetLeft - (navWidth - tabWidth) / 2, immediate); }, // animate the scrollLeft of nav scrollTo: function scrollTo(el, from, to, immediate) { if (immediate) { el.scrollLeft += to - from; return; } var count = 0; var frames = Math.round(this.duration * 1000 / 16); var animate = function animate() { el.scrollLeft += (to - from) / frames; /* istanbul ignore next */ if (++count < frames) { (0, _raf.raf)(animate); } }; animate(); }, // render title slot of child tab renderTitle: function renderTitle(el, index) { var _this3 = this; this.$nextTick(function () { var title = _this3.$refs.title[index]; title.parentNode.replaceChild(el, title); }); }, getTabStyle: function getTabStyle(item, index) { var style = {}; var color = this.color; var active = index === this.curActive; var isCard = this.type === 'card'; // theme color if (color) { if (!item.disabled && isCard && !active) { style.color = color; } if (!item.disabled && isCard && active) { style.backgroundColor = color; } if (isCard) { style.borderColor = color; } } var titleColor = active ? this.titleActiveColor : this.titleInactiveColor; if (titleColor) { style.color = titleColor; } if (this.scrollable && this.ellipsis) { style.flexBasis = 88 / this.swipeThreshold + '%'; } return style; } }, render: function render(h) { var _this4 = this; var type = this.type, ellipsis = this.ellipsis, animated = this.animated, scrollable = this.scrollable; var Nav = this.tabs.map(function (tab, index) { return h("div", { "ref": "tabs", "refInFor": true, "class": tabBem({ active: index === _this4.curActive, disabled: tab.disabled, complete: !ellipsis }), "style": _this4.getTabStyle(tab, index), "on": { "click": function click() { _this4.onClick(index); } } }, [h("span", { "ref": "title", "refInFor": true, "class": { 'van-ellipsis': ellipsis } }, [tab.title])]); }); return h("div", { "class": bem([type]) }, [h("div", { "ref": "wrap", "style": this.wrapStyle, "class": [bem('wrap', { scrollable: scrollable }), { 'van-hairline--top-bottom': type === 'line' }] }, [h("div", { "ref": "nav", "class": bem('nav', [type]), "style": this.navStyle }, [this.slots('nav-left'), type === 'line' && h("div", { "class": bem('line'), "style": this.lineStyle }), Nav, this.slots('nav-right')])]), h("div", { "ref": "content", "class": bem('content', { animated: animated }) }, [animated ? h("div", { "class": bem('track'), "style": this.trackStyle }, [this.slots()]) : this.slots()])]); } }); exports["default"] = _default;