| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464 |
- "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;
|