@fesjs/fes-design
Version:
fes-design for PC
153 lines (150 loc) • 5.42 kB
JavaScript
import { defineComponent, getCurrentInstance, ref, inject, reactive, onMounted, onUnmounted, withDirectives, createVNode, vShow, computed } from 'vue';
import { useTheme } from '../_theme/useTheme';
import { CAROUSEL_ITEM_NAME, provideKey, CAROUSEL_NAME, CARD_SCALE } from './const';
import { carouselItemProps } from './interface';
const useItemStyle = direction => {
const itemStyleState = reactive({
translate: 0,
scale: 1
});
const itemStyle = computed(() => {
const translateType = direction.value === 'vertical' ? 'translateY' : 'translateX';
const value = `${translateType}(${itemStyleState.translate}px) scale(${itemStyleState.scale}, ${itemStyleState.scale})`;
const style = {
transform: value
};
return style;
});
const setItemStyle = (translate, scale) => {
itemStyleState.translate = translate;
if (scale) {
itemStyleState.scale = scale;
}
};
return {
itemStyle,
setItemStyle
};
};
var carouselItem = defineComponent({
name: CAROUSEL_ITEM_NAME,
props: carouselItemProps,
setup(props, _ref) {
let {
slots
} = _ref;
useTheme();
const instance = getCurrentInstance();
const slideRef = ref(null);
const {
prefixCls,
direction,
wrapperRef,
rootProps,
slideChildren,
setActiveItem,
addItem,
removeItem
} = inject(provideKey);
const {
itemStyle,
setItemStyle
} = useItemStyle(direction);
function processIndex(index, activeIndex, length) {
if (activeIndex === 0 && index === length - 1) {
return -1;
}
if (activeIndex === length - 1 && index === 0) {
return length;
}
if (index < activeIndex - 1 && activeIndex - index >= length / 2) {
return length + 1;
}
if (index > activeIndex + 1 && index - activeIndex >= length / 2) {
return -2;
}
return index;
}
const itemStatus = reactive({
hover: false,
active: false,
inStage: false,
animating: false
});
function calcCardTranslate(index, activeIndex) {
var _wrapperRef$value;
const parentWidth = ((_wrapperRef$value = wrapperRef.value) === null || _wrapperRef$value === void 0 ? void 0 : _wrapperRef$value.offsetWidth) || 0;
if (itemStatus.inStage) {
return parentWidth * ((2 - CARD_SCALE) * (index - activeIndex) + 1) / 4;
}
if (index < activeIndex) {
return -(1 + CARD_SCALE) * parentWidth / 4;
}
return (3 + CARD_SCALE) * parentWidth / 4;
}
function calcTranslate(index, activeIndex, isVertical) {
var _wrapperRef$value2, _wrapperRef$value3;
const distance = (isVertical ? (_wrapperRef$value2 = wrapperRef.value) === null || _wrapperRef$value2 === void 0 ? void 0 : _wrapperRef$value2.offsetHeight : (_wrapperRef$value3 = wrapperRef.value) === null || _wrapperRef$value3 === void 0 ? void 0 : _wrapperRef$value3.offsetWidth) || 0;
return distance * (index - activeIndex);
}
const itemReady = ref(false);
const translateItem = (index, activeIndex, oldIndex) => {
const length = slideChildren.value.length;
if (rootProps.type !== 'card' && oldIndex !== undefined) {
itemStatus.animating = index === activeIndex || index === oldIndex;
}
if (index !== activeIndex && length > 2 && rootProps.loop) {
index = processIndex(index, activeIndex, length);
}
if (rootProps.type === 'card') {
if (direction.value === 'vertical') {
console.warn(`[${CAROUSEL_ITEM_NAME}]: ${CAROUSEL_NAME} vertical direction is not supported in card mode.`);
}
itemStatus.inStage = Math.round(Math.abs(index - activeIndex)) <= 1;
itemStatus.active = index === activeIndex;
setItemStyle(calcCardTranslate(index, activeIndex), itemStatus.active ? 1 : CARD_SCALE);
} else {
itemStatus.active = index === activeIndex;
const isVertical = direction.value === 'vertical';
setItemStyle(calcTranslate(index, activeIndex, isVertical));
}
itemReady.value = true;
};
const onClickSlide = () => {
if (rootProps.type === 'card') {
const index = slideChildren.value.map(item => item.uid).indexOf(instance.uid);
setActiveItem(index);
}
};
onMounted(() => {
addItem({
uid: instance.uid,
itemkey: props.itemkey,
states: itemStatus,
translateItem
});
});
onUnmounted(() => {
removeItem(instance.uid);
});
return () => {
var _slots$default;
return withDirectives(createVNode("div", {
"ref": slideRef,
"class": {
[`${prefixCls}-item`]: true,
[`${prefixCls}-item-card`]: rootProps.type === 'card',
'is-in-stage': itemStatus.inStage,
'is-hover': itemStatus.hover,
'is-active': itemStatus.active,
'is-animating': itemStatus.animating
},
"style": itemStyle.value,
"onClick": onClickSlide
}, [rootProps.type === 'card' && withDirectives(createVNode("div", {
"class": `${prefixCls}-item-mask`
}, null), [[vShow, !itemStatus.active]]), (_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots)]), [[vShow, itemReady.value]]);
};
}
});
export { carouselItem as default };