Path: blob/main/frontend/vue/components/Carousel/Carousel.vue
3375 views
<template> <section class="carousel"> <div class="carousel__elements-wrapper"> <div ref="elementsWrapperRef" class="carousel__elements" :style="`--active-slide-index: ${selectedInt}`" > <slot /> </div> </div> <DotsSelector ref="dotsSelectorRef" class="carousel__selector" :count="count" :disable-arrows="disableArrows" @onSelectedChange="selectedIntChange" /> </section> </template> <script lang="ts"> import { ref } from '@vue/reactivity' import { Options, prop, Vue } from 'vue-class-component' import DotsSelector from '../common/DotsSelector.vue' class Props { disableArrows = prop<boolean>({ default: false, required: true }) } @Options({ components: { DotsSelector } }) export default class Carousel extends Vue.with(Props) { elementsWrapperRef = ref<HTMLElement | null>(null) get elementsWrapper () { return (this.elementsWrapperRef as unknown as HTMLElement) } dotsSelectorRef = ref<DotsSelector | null>(null) get dotsSelector () { return (this.dotsSelectorRef as unknown as DotsSelector) } selectedInt = 0 count = 0 mounted () { this.updateSlides() } updateSlides () { this.selectedIntChange(0) this.count = this.elementsWrapper.childElementCount } selectedIntChange (value :number) { const oldValue = this.selectedInt const oldSelectedEl = this.elementsWrapper.children[oldValue] if (oldSelectedEl) { oldSelectedEl.classList.remove('active') } this.selectedInt = value const selectedEl = this.elementsWrapper.children[value] if (selectedEl) { selectedEl.classList.add('active') } this.$emit('onSelectedChange', value) } nextSlide () { this.dotsSelector.nextDot() } } </script> <style scoped lang="scss"> .carousel { &__elements-wrapper { padding: 15px; } &__elements { display: flex; flex-wrap: nowrap; font-size: 0.875rem; line-height: 1.7rem; transform: translateX(calc(-100% * var(--active-slide-index))); & > ::v-deep(*) { flex: 0 0 100%; } & > ::v-deep(:not(.active)) { visibility: hidden; } } &__selector { margin-top: 30px; } } </style>