Files
web-temp/layers/components/blocks/slide/Default.vue
2025-11-06 13:57:50 +09:00

98 lines
2.3 KiB
Vue

<script setup lang="ts">
import { Splide } from '@splidejs/vue-splide'
import type { Splide as SplideType, ResponsiveOptions } from '@splidejs/splide'
import type { PageDataResourceGroups } from '#layers/types/api/pageData'
interface Props {
type?: ResponsiveOptions['type']
slideItemLength?: number
gap?: number
autoplay?: boolean
perPage?: number
drag?: boolean
arrows?: boolean
pagination?: boolean
paginationData?: PageDataResourceGroups
destroy?: boolean
breakpoints?: ResponsiveOptions['breakpoints']
}
const props = withDefaults(defineProps<Props>(), {
gap: 0,
autoplay: false,
perPage: 1,
drag: true,
arrows: true,
pagination: true,
destroy: false,
})
const emit = defineEmits(['mounted', 'move', 'arrowClick'])
// Splide 화살표 로직을 위한 composable 사용
const { addArrowClickListeners } = useSplideArrow()
const slideType = computed(() => {
if (props.type) return props.type
return (props.slideItemLength ?? 0) > 1 ? 'loop' : 'slide'
})
const options = computed((): ResponsiveOptions => {
return {
type: slideType.value,
autoWidth: true,
autoHeight: true,
gap: props.gap,
perPage: props.perPage,
speed: 500,
updateOnMove: true,
autoplay: props.autoplay,
drag: props.drag,
arrows: props.arrows,
pagination: props.pagination,
destroy: props.destroy,
classes: {
arrows: 'splide-arrows',
arrow: 'splide-arrow',
prev: 'arrow-prev',
next: 'arrow-next',
pagination: 'splide-pagination-bullets',
page: 'splide-pagination-bullet',
},
...(props.breakpoints ? { breakpoints: props.breakpoints } : {}),
}
})
const handleSplideMounted = (splide: SplideType) => {
emit('mounted', splide)
// 화살표 버튼 클릭 이벤트 리스너 추가
nextTick(() => {
addArrowClickListeners(splide, (direction, targetIndex) => {
emit('arrowClick', direction, targetIndex)
})
})
}
const handleMove = (
splide: SplideType,
newIndex: number,
oldIndex: number,
destIndex: number
) => {
emit('move', splide, newIndex, oldIndex, destIndex)
}
</script>
<template>
<Splide
:options="options"
:style="getPaginationClass(props?.paginationData)"
@splide:mounted="handleSplideMounted"
@splide:move="handleMove"
>
<slot />
</Splide>
</template>