import {
onComplete,
handleMouseEnter,
handleMouseLeave,
itemInStage,
handleButtonEnter,
handleButtonLeave,
resetItemPosition,
playSlides,
pauseTimer,
startTimer,
setActiveItem,
prev,
next,
handleIndicatorClick,
handleIndicatorHover,
watchItems,
watchActiveIndex,
watchAutoplay,
throttledArrowClick,
throttledIndicatorHover,
computedHasLabel,
touchstart,
touchmove,
touchend,
computedStyle,
simulateTouch,
computedHasButtons,
computedHasIndicators,
canActive
} from './index'
import { addResizeListener, removeResizeListener } from '@opentiny/utils'
export const api = [
'state',
'items',
'activeIndex',
'containerWidth',
'hover',
'hasLabel',
'onComplete',
'handleMouseEnter',
'handleMouseLeave',
'itemInStage',
'handleButtonEnter',
'handleButtonLeave',
'updateItems',
'resetItemPosition',
'playSlides',
'pauseTimer',
'startTimer',
'setActiveItem',
'prev',
'next',
'handleIndicatorClick',
'handleIndicatorHover',
'throttledArrowClick',
'throttledIndicatorHover',
'touchstart',
'touchmove',
'touchend'
]
const initState = ({ reactive, computed, api }) => {
const state = reactive({
itemsTranslate: [],
items: [],
timer: null,
hover: false,
activeIndex: -1,
completed: false,
delta: 0,
containerWidth: 0,
deltaPos: {
X: 0,
Y: 0
},
startPos: {
X: 0,
Y: 0
},
offsetPos: {
X: 0,
Y: 0
},
touchTime: 0,
size: 0,
direction: '',
moving: false,
isCorrectDirection: false,
moveDisable: false,
noTouchNode: ['svg', 'BUTTON', 'path', 'g'],
style: computed(() => api.computedStyle()),
hasLabel: computed(() => api.computedHasLabel(state.items)),
hasButtons: computed(() => api.computedHasButtons()),
hasIndicators: computed(() => api.computedHasIndicators())
})
return state
}
const initApi = ({ vm, api, state, props, emit, mode }) => {
Object.assign(api, {
state,
computedHasLabel,
touchend: touchend({ props, state, api }),
touchstart: touchstart({ props, state, api }),
touchmove: touchmove({ props, state, vm }),
playSlides: playSlides({ api, props, state }),
onComplete: onComplete({ api, count: 0, emit, props, state }),
pauseTimer: pauseTimer(state),
itemInStage: itemInStage(state),
resetItemPosition: resetItemPosition(state),
watchItems: watchItems({ api, props }),
handleButtonLeave: handleButtonLeave(state),
handleIndicatorClick: handleIndicatorClick({ api, state }),
handleIndicatorHover: handleIndicatorHover({ api, props, state }),
watchActiveIndex: watchActiveIndex({ api, emit }),
watchAutoplay: watchAutoplay(api),
startTimer: startTimer({ api, props, state }),
prev: prev({ api, state }),
next: next({ api, state }),
throttledArrowClick: throttledArrowClick(api),
setActiveItem: setActiveItem({ api, props, state }),
handleMouseEnter: handleMouseEnter({ api, state }),
handleMouseLeave: handleMouseLeave({ api, state }),
throttledIndicatorHover: throttledIndicatorHover(api),
handleButtonEnter: handleButtonEnter({ api, state }),
computedStyle: computedStyle({ props }),
simulateTouch: simulateTouch({ props, vm }),
computedHasButtons: computedHasButtons({ props, state, mode }),
computedHasIndicators: computedHasIndicators({ props, state, mode }),
canActive: canActive(props)
})
}
const initWatch = ({ watch, props, api, state }) => {
watch(() => props.autoplay, api.watchAutoplay)
watch(
() => props.loop,
() => api.setActiveItem(state.activeIndex)
)
}
export const renderless = (
props,
{ computed, onMounted, onBeforeUnmount, reactive, watch, provide },
{ vm, parent, emit, mode }
) => {
const api = {}
const state = initState({ reactive, computed, api })
initApi({ vm, api, state, props, emit, mode })
const { updateItems } = useItems({ api, vm, onMounted, state, watch })
api.updateItems = updateItems
useActiveIndex({ api, parent, props, state, watch })
useResizeListener({ api, onBeforeUnmount, onMounted, parent })
provide('CarouselVm', vm)
initWatch({ watch, props, api, state })
onMounted(() => {
api.startTimer()
api.onComplete(state.items.length)
api.simulateTouch()
})
parent.$on('updateItems', api.updateItems)
parent.$on('complete', () => {
api.onComplete(state.items.length)
})
return api
}
export const useItems = ({ api, onMounted, state, watch }) => {
const updateItems = (carouselItemVm) => {
if (carouselItemVm && !state.items.includes(carouselItemVm)) {
state.items.push(carouselItemVm)
}
}
watch(
() => state.items,
(value) => state.completed && api.watchItems(value)
)
onMounted(updateItems)
return {
updateItems
}
}
export const useActiveIndex = ({ api, state, watch }) => {
watch(
() => state.activeIndex,
(value, oldValue) => api.watchActiveIndex({ value, oldValue }),
{ immediate: true }
)
}
export const useResizeListener = ({ api, onBeforeUnmount, onMounted, parent }) => {
onMounted(() => {
addResizeListener(parent.$el, api.resetItemPosition)
})
onBeforeUnmount(() => {
if (parent.$el) {
removeResizeListener(parent.$el, api.resetItemPosition)
}
})
}