UNPKG

@fesjs/fes-design

Version:
153 lines (150 loc) 5.42 kB
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 };