taro-ui-vue3
Version:
Taro UI Rewritten in Vue 3.0
225 lines (224 loc) • 6.93 kB
JavaScript
var __defProp = Object.defineProperty;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value;
var __objSpread = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
import {
h,
computed,
defineComponent,
mergeProps,
onMounted,
ref,
reactive,
watch
} from "vue";
import {ScrollView, View, Text} from "@tarojs/components";
import Taro from "@tarojs/taro";
import {uuid} from "../utils/common";
const ENV = Taro.getEnv();
const MIN_DISTANCE = 100;
const MAX_INTERVAL = 10;
const AtTabs = defineComponent({
name: "AtTabs",
props: {
tabDirection: {
type: String,
default: "horizontal"
},
height: {
type: String,
default: ""
},
current: {
type: Number,
default: 0
},
scroll: Boolean,
animated: {
type: Boolean,
default: true
},
swipeable: {
type: Boolean,
default: true
},
tabList: {
type: Array,
default: []
},
onClick: {
type: Function,
default: () => (index, event) => {
}
}
},
setup(props, {attrs, slots}) {
const _tabId = ref(uuid());
const _touchDot = ref(0);
const _timer = ref(null);
const _interval = ref(0);
const _isMoving = ref(false);
const tabHeaderRef = ref(null);
const state = reactive({
_scrollLeft: 0,
_scrollTop: 0,
_scrollIntoView: ""
});
const scrollX = computed(() => props.tabDirection === "horizontal");
const scrollY = computed(() => props.tabDirection === "vertical");
const rootClass = computed(() => ({
"at-tabs": true,
"at-tabs--scroll": props.scroll,
[`at-tabs--${props.tabDirection}`]: true,
[`at-tabs--${ENV}`]: true
}));
const heightStyle = computed(() => ({height: props.height}));
const underlineStyle = computed(() => ({
height: props.tabDirection === "vertical" ? `${props.tabList.length * 100}%` : "1PX",
width: props.tabDirection === "horizontal" ? `${props.tabList.length * 100}%` : "1PX"
}));
const bodyStyle = computed(() => {
const bodyStyle2 = __objSpread({}, heightStyle.value);
let transformStyle = `translate3d(0px, -${props.current * 100}%, 0px)`;
if (props.tabDirection === "horizontal") {
transformStyle = `translate3d(-${props.current * 100}%, 0px, 0px)`;
}
Object.assign(bodyStyle2, {
transform: transformStyle,
"-webkit-transform": transformStyle
});
if (!props.animated) {
bodyStyle2.transition = "unset";
}
return bodyStyle2;
});
const tabItemClass = computed(() => (idx) => ({
"at-tabs__item": true,
"at-tabs__item--active": props.current === idx
}));
function updateState(idx) {
if (props.scroll) {
if (ENV !== Taro.ENV_TYPE.WEB) {
const index = Math.max(idx - 1, 0);
state._scrollIntoView = `tab${_tabId.value}${index}`;
} else {
const index = Math.max(idx - 1, 0);
const prevTabItem = tabHeaderRef.value.$el.children[index];
if (prevTabItem) {
state._scrollTop = prevTabItem.offsetTop;
state._scrollLeft = prevTabItem.offsetLeft;
}
}
}
}
function handleClick(index, event) {
props.onClick(index, event);
}
function handleTouchStart(e) {
if (!props.swipeable || props.tabDirection === "vertical")
return;
_touchDot.value = e.touches[0].pageX;
_timer.value = setInterval(() => {
_interval.value++;
}, 100);
}
function handleTouchMove(e) {
if (!props.swipeable || props.tabDirection === "vertical")
return;
const touchMove = e.touches[0].pageX;
const moveDistance = touchMove - _touchDot.value;
const maxIndex = props.tabList.length;
if (!_isMoving.value && _interval.value < MAX_INTERVAL && _touchDot.value > 20) {
if (props.current + 1 < maxIndex && moveDistance <= -MIN_DISTANCE) {
_isMoving.value = true;
handleClick(props.current + 1, e);
} else if (props.current - 1 >= 0 && moveDistance >= MIN_DISTANCE) {
_isMoving.value = true;
handleClick(props.current - 1, e);
}
}
}
function handleTouchEnd() {
if (!props.swipeable || props.tabDirection === "vertical")
return;
clearInterval(_timer.value);
_interval.value = 0;
_isMoving.value = false;
}
watch(() => props.current, (current) => {
updateState(current);
});
onMounted(() => {
updateState(props.current);
});
return () => {
const tabItems = props.tabList.map((item, idx) => h(View, {
id: `tab${_tabId.value}${idx}`,
key: item.title,
class: tabItemClass.value(idx),
onTap: handleClick.bind(this, idx)
}, {
default: () => [
h(Text, {
style: "white-space: nowrap;"
}, {default: () => item.title}),
h(View, {class: "at-tabs__item-underline"})
]
}));
return h(View, mergeProps(attrs, {
class: rootClass.value,
style: heightStyle.value
}), {
default: () => [
props.scroll ? h(ScrollView, mergeProps(ENV === Taro.ENV_TYPE.WEB ? {ref: (el) => {
tabHeaderRef.value = el;
}} : {}, {
id: _tabId.value,
class: "at-tabs__header",
style: heightStyle.value,
scrollX: scrollX.value,
scrollY: scrollY.value,
scrollWithAnimation: true,
scrollLeft: state._scrollLeft,
scrollTop: state._scrollTop,
scrollIntoView: state._scrollIntoView
}), {default: () => tabItems}) : h(View, {
id: _tabId.value,
class: "at-tabs__header"
}, {default: () => tabItems}),
h(View, {
class: "at-tabs__body",
style: bodyStyle.value,
onTouchstart: handleTouchStart,
onTouchend: handleTouchEnd,
onTouchmove: handleTouchMove
}, {
default: () => [
h(View, {
class: "at-tabs__underline",
style: underlineStyle.value
}),
slots.default && slots.default()
]
})
]
});
};
}
});
var tabs_default = AtTabs;
export {
tabs_default as default
};