# ZeenSpeakerSection

ZeenSpeakerSection секция включающая в себя слайдер и набор карточек с данными спикера

# Примеры:

  • Все значения по умолчанию

    :speakers="speakers"

    Спикеры

    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
  • Смена позиции стрелок слайдера

    :speakers="speakers"
    :arrow-position="'bottom'"

    Спикеры

    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
  • Активация пагинации

    :speakers="speakers"
    :arrow-position="'bottom'"
    is-pagination

    Спикеры

    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
  • Передача данных в карточку спикера

    :speakers="speakers"
    :arrow-position="'bottom'"
    :attrsSpeaker="{
    theme: 'main', }"
    is-pagination

    Спикеры

    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки
    Компания

    Константин Константинопольский

    Главный дизайнер Специальная специализация, которую специально написали и растянули на три строки

# Slots

Название Описание
top-icon-next Топ иконка next
top-icon-prev Топ иконка prev
icon-next Нижняя иконка next
icon-prev Нижняя иконка prev

# props

Название Тип Обязательный По умолчанию Описание
speakers Object + - Принимает в себя объект с данными спикера совпадает с данными которые приходят с сервера подробнее см. ниже
mainHeadlineAttrs Object - - Принимает в себя объект с props для компонента ZeenHeadline, где ключом будет является props который ожидает получить компонент ZeenHeadline, а значением будет являтся присваемовое значение
breakpoints Object - - Объект с брейкпоинтами
title String - Спикеры Заголовок блока спикеров
arrowPosition String - top Принимает два значения top и bottom. Перемещает вверх или вниз стрелки слайдера
isPagination Boolean - false Наличие пагинации
isClickableBullets Boolean - true Будут ли кликабельными буллиты в слайдере

# Speakers - код объекта

Код объекта

export default [
  {
    id: '3bb4a22f-d533-404a-8d2f-7ad4e1d89f5214',
    login: 'spe4',
    phone: '555-35-35',
    picture: 'https://enel.com.tr/wp-content/uploads/2019/10/mt-2.jpg',
    gender: '',
    birthdate: null,
    country: '',
    city: '',
    company_name: 'Компания',
    facebook_link: '1',
    vk_link: '2',
    twitter_link: '3',
    instagram_link: '4',
    company_field_list: [],
    interest_list: [],
    name: 'Константин Константинопольский',
    about: 'Специальная специализация, которую специально написали и растянули на три строки',
    position: 'Главный дизайнер',
    verified: false,
    onboarding_passed: false,
    registered_conference_id: null,
    reg_conf_id: null,
    message_privacy: 'all_users',
    mailing_policies: {},
    locale: 'ru',
    email: 'spe4@spe4',
    avatar_url: 'https://enel.com.tr/wp-content/uploads/2019/10/mt-2.jpg',
    speech_ids: ['3d2a60af-71ad-4097-a9b6-9c3c94a5bafc', 'ad41dc63-d924-4b47-a88a-1cab1c49e886'],
    priority: 0,
    created_at: 1619469432,
  },
  {
    id: '3bb4a22f-d533-404a-8d2f-7ad4e1d89f1452',
    login: 'spe4',
    phone: '555-35-35',
    picture: 'https://enel.com.tr/wp-content/uploads/2019/10/mt-2.jpg',
    gender: '',
    birthdate: null,
    country: '',
    city: '',
    company_name: 'Компания',
    facebook_link: '1',
    vk_link: '2',
    twitter_link: '3',
    instagram_link: '4',
    company_field_list: [],
    interest_list: [],
    name: 'Константин Константинопольский',
    about: 'Специальная специализация, которую специально написали и растянули на три строки',
    position: 'Главный дизайнер',
    verified: false,
    onboarding_passed: false,
    registered_conference_id: null,
    reg_conf_id: null,
    message_privacy: 'all_users',
    mailing_policies: {},
    locale: 'ru',
    email: 'spe4@spe4',
    avatar_url: 'https://enel.com.tr/wp-content/uploads/2019/10/mt-2.jpg',
    speech_ids: ['3d2a60af-71ad-4097-a9b6-9c3c94a5bafc', 'ad41dc63-d924-4b47-a88a-1cab1c49e886'],
    priority: 0,
    created_at: 1619469432,
  },
  {
    id: '3bb4a22f-d533-404a-8d2f-7ad4e1d8149f52',
    login: 'spe4',
    phone: '555-35-35',
    picture: 'https://enel.com.tr/wp-content/uploads/2019/10/mt-2.jpg',
    gender: '',
    birthdate: null,
    country: '',
    city: '',
    company_name: 'Компания',
    facebook_link: '1',
    vk_link: '2',
    twitter_link: '3',
    instagram_link: '4',
    company_field_list: [],
    interest_list: [],
    name: 'Константин Константинопольский',
    about: 'Специальная специализация, которую специально написали и растянули на три строки',
    position: 'Главный дизайнер',
    verified: false,
    onboarding_passed: false,
    registered_conference_id: null,
    reg_conf_id: null,
    message_privacy: 'all_users',
    mailing_policies: {},
    locale: 'ru',
    email: 'spe4@spe4',
    avatar_url: 'https://enel.com.tr/wp-content/uploads/2019/10/mt-2.jpg',
    speech_ids: ['3d2a60af-71ad-4097-a9b6-9c3c94a5bafc', 'ad41dc63-d924-4b47-a88a-1cab1c49e886'],
    priority: 0,
    created_at: 1619469432,
  },
  {
    id: '3bb4a22f-d533-404a-8d2f-7ad4e1d1489f52',
    login: 'spe4',
    phone: '555-35-35',
    picture: 'https://enel.com.tr/wp-content/uploads/2019/10/mt-2.jpg',
    gender: '',
    birthdate: null,
    country: '',
    city: '',
    company_name: 'Компания',
    facebook_link: '1',
    vk_link: '2',
    twitter_link: '3',
    instagram_link: '4',
    company_field_list: [],
    interest_list: [],
    name: 'Константин Константинопольский',
    about: 'Специальная специализация, которую специально написали и растянули на три строки',
    position: 'Главный дизайнер',
    verified: false,
    onboarding_passed: false,
    registered_conference_id: null,
    reg_conf_id: null,
    message_privacy: 'all_users',
    mailing_policies: {},
    locale: 'ru',
    email: 'spe4@spe4',
    avatar_url: 'https://enel.com.tr/wp-content/uploads/2019/10/mt-2.jpg',
    speech_ids: ['3d2a60af-71ad-4097-a9b6-9c3c94a5bafc', 'ad41dc63-d924-4b47-a88a-1cab1c49e886'],
    priority: 0,
    created_at: 1619469432,
  },
  {
    id: '3bb4a22f-d533-404a-8d2f-7ad4e1d254189f52',
    login: 'spe4',
    phone: '555-35-35',
    picture: 'https://enel.com.tr/wp-content/uploads/2019/10/mt-2.jpg',
    gender: '',
    birthdate: null,
    country: '',
    city: '',
    company_name: 'Компания',
    facebook_link: '1',
    vk_link: '2',
    twitter_link: '3',
    instagram_link: '4',
    company_field_list: [],
    interest_list: [],
    name: 'Константин Константинопольский',
    about: 'Специальная специализация, которую специально написали и растянули на три строки',
    position: 'Главный дизайнер',
    verified: false,
    onboarding_passed: false,
    registered_conference_id: null,
    reg_conf_id: null,
    message_privacy: 'all_users',
    mailing_policies: {},
    locale: 'ru',
    email: 'spe4@spe4',
    avatar_url: 'https://enel.com.tr/wp-content/uploads/2019/10/mt-2.jpg',
    speech_ids: ['3d2a60af-71ad-4097-a9b6-9c3c94a5bafc', 'ad41dc63-d924-4b47-a88a-1cab1c49e886'],
    priority: 0,
    created_at: 1619469432,
  },
  {
    id: '3bb4a22f-d533-404a-8d2f-7ad2542544e1d89f52',
    login: 'spe4',
    phone: '555-35-35',
    picture: 'https://enel.com.tr/wp-content/uploads/2019/10/mt-2.jpg',
    gender: '',
    birthdate: null,
    country: '',
    city: '',
    company_name: 'Компания',
    facebook_link: '1',
    vk_link: '2',
    twitter_link: '3',
    instagram_link: '4',
    company_field_list: [],
    interest_list: [],
    name: 'Константин Константинопольский',
    about: 'Специальная специализация, которую специально написали и растянули на три строки',
    position: 'Главный дизайнер',
    verified: false,
    onboarding_passed: false,
    registered_conference_id: null,
    reg_conf_id: null,
    message_privacy: 'all_users',
    mailing_policies: {},
    locale: 'ru',
    email: 'spe4@spe4',
    avatar_url: 'https://enel.com.tr/wp-content/uploads/2019/10/mt-2.jpg',
    speech_ids: ['3d2a60af-71ad-4097-a9b6-9c3c94a5bafc', 'ad41dc63-d924-4b47-a88a-1cab1c49e886'],
    priority: 0,
    created_at: 1619469432,
  },
]

# Source Code - исходный код компонента

<template>
  <section class="speaker-section" ref="main">
    <ZeenContainer>
      <div class="swiper">
        <div class="speaker-section__actions js-program-actions">
          <ZeenHeadline class="speaker-section__main-headline" v-bind="mainHeadlineAttrs">{{ title }}</ZeenHeadline>
          <slot name="top-btn" />
          <div v-if="arrowPosition === 'top'" class="speaker-section__buttons-group">
            <button class="js-program-btn js-program-next swiper-button-disabled speaker-section__btn" ref="btnPrevTop">
              <slot name="top-icon-next">
                <svg width="6" height="11" viewBox="0 0 6 11" xmlns="http://www.w3.org/2000/svg">
                  <path
                    fill-rule="evenodd"
                    clip-rule="evenodd"
                    d="M5.35667 0.252601C4.94389 -0.114317 4.31182 -0.077136 3.9449 0.335647L0.252591 4.48949C-0.0841969 4.86838 -0.0841969 5.43933 0.252591 5.81822L3.9449 9.97207C4.31182 10.3848 4.94389 10.422 5.35667 10.0551C5.76945 9.68819 5.80664 9.05612 5.43972 8.64334L2.33795 5.15386L5.43972 1.66437C5.80664 1.25159 5.76945 0.619519 5.35667 0.252601Z"
                  />
                </svg>
              </slot>
            </button>
            <button class="js-program-btn js-program-prev speaker-section__btn" ref="btnNextTop">
              <slot name="top-icon-prev">
                <svg width="6" height="11" viewBox="0 0 6 11" xmlns="http://www.w3.org/2000/svg">
                  <path
                    fill-rule="evenodd"
                    clip-rule="evenodd"
                    d="M5.35576 10.055C4.94298 10.4219 4.3109 10.3848 3.94399 9.97197L0.251678 5.81812C-0.0851092 5.43924 -0.0851092 4.86828 0.251678 4.4894L3.94399 0.33555C4.3109 -0.0772324 4.94298 -0.114413 5.35576 0.252505C5.76854 0.619423 5.80572 1.2515 5.4388 1.66428L2.33704 5.15376L5.4388 8.64324C5.80572 9.05603 5.76854 9.6881 5.35576 10.055Z"
                  />
                </svg>
              </slot>
            </button>
          </div>
        </div>
        <div class="speaker-section__swiper swiper-container" ref="slider">
          <div class="swiper-wrapper">
            <div class="swiper-slide" v-for="speaker in speakers" :key="speaker.id">
              <ZeenSpeakerCard
                :speaker="speaker"
                :picture-attrs="{src: speaker.picture}"
                v-bind="attrsSpeaker"
                v-on="speakerEvents"
              >
                <template v-for="(slot, slotName) in speakerSlots" v-slot:[slotName]="params">
                  <slot :name="`${speakerPrefix}${slotName}`" v-bind="params" />
                </template>
              </ZeenSpeakerCard>
            </div>
            <slot name="swiper-part" />
          </div>
          <div v-if="isPagination" class="swiper-pagination" ref="pagination"></div>
        </div>
        <div
          v-if="arrowPosition === 'bottom'"
          class="speaker-section__buttons-group speaker-section__buttons-group_bottom"
        >
          <button
            class="js-program-btn js-program-prev swiper-button-disabled speaker-section__btn"
            ref="btnPrevBottom"
          >
            <slot name="icon-prev">
              <svg width="6" height="11" viewBox="0 0 6 11" xmlns="http://www.w3.org/2000/svg">
                <path
                  fill-rule="evenodd"
                  clip-rule="evenodd"
                  d="M0.335647 0.252601C0.74843 -0.114317 1.3805 -0.077136 1.74742 0.335647L5.43973 4.48949C5.77652 4.86838 5.77652 5.43933 5.43973 5.81822L1.74742 9.97207C1.3805 10.3848 0.74843 10.422 0.335647 10.0551C-0.077136 9.68819 -0.114317 9.05612 0.252601 8.64334L3.35436 5.15386L0.252601 1.66437C-0.114317 1.25159 -0.077136 0.619519 0.335647 0.252601Z"
                />
              </svg>
            </slot>
          </button>
          <button class="js-program-btn js-program-next speaker-section__btn" ref="btnNextBottom">
            <slot name="icon-next">
              <svg width="6" height="11" viewBox="0 0 6 11" xmlns="http://www.w3.org/2000/svg">
                <path
                  fill-rule="evenodd"
                  clip-rule="evenodd"
                  d="M0.334734 10.055C0.747517 10.4219 1.37959 10.3848 1.74651 9.97197L5.43882 5.81812C5.7756 5.43924 5.7756 4.86828 5.43882 4.4894L1.74651 0.33555C1.37959 -0.0772324 0.747517 -0.114413 0.334734 0.252505C-0.0780483 0.619423 -0.115229 1.2515 0.251689 1.66428L3.35345 5.15376L0.251689 8.64324C-0.115229 9.05603 -0.0780483 9.6881 0.334734 10.055Z"
                />
              </svg>
            </slot>
          </button>
        </div>
      </div>
    </ZeenContainer>
  </section>
</template>

<script>
import Vue from 'vue'
import Swiper from 'swiper/bundle'
import ZeenHeadline from '../../components/ZeenHeadline/ZeenHeadline'
import ZeenSpeakerCard from '../../components/ZeenSpeakerCard/ZeenSpeakerCard'
import 'swiper/swiper-bundle.css'
import ZeenContainer from '../../components/ZeenContainer/ZeenContainer'
import {createSlotsFor, createEventsFor} from '../../helpers/createBlockData'

export default {
  name: 'ZeenSpeakerSection',
  components: {ZeenContainer, ZeenSpeakerCard, ZeenHeadline},
  inheritAttrs: false,
  props: {
    title: {
      type: String,
      default: 'Спикеры',
    },
    arrowPosition: {
      type: String,
      default: 'top',
    },
    isPagination: {
      type: Boolean,
      default: false,
    },
    isClickableBullets: {
      type: Boolean,
      default: true,
    },
    attrsSpeaker: {
      type: Object,
      require: false,
    },
    speakers: {
      type: Array,
      require: true,
    },
    mainHeadlineAttrs: {
      type: Object,
      require: false,
      default: () => ({type: 'dark-48'}),
    },
    breakpoints: {
      type: Object,
      require: false,
      default: () => ({
        1400: {
          slidesPerView: 4.5,
          spaceBetween: 20,
        },
        1200: {
          slidesPerView: 4.1,
          spaceBetween: 20,
        },
        992: {
          slidesPerView: 3.5,
          spaceBetween: 20,
        },
        768: {
          slidesPerView: 3.1,
          spaceBetween: 20,
        },
        560: {
          slidesPerView: 2.4,
          spaceBetween: 10,
        },
        480: {
          slidesPerView: 1.8,
          spaceBetween: 10,
        },
        360: {
          slidesPerView: 1.4,
          spaceBetween: 10,
        },
        300: {
          slidesPerView: 1.1,
          spaceBetween: 10,
        },
        1: {
          slidesPerView: 1.1,
          spaceBetween: 10,
        },
        // Дефолт значение, нужно чтобы карточка спикера
        // не растягивалась на фулл при загрузке
        0: {
          slidesPerView: 4.5,
          spaceBetween: 10,
        },
      }),
    },
  },
  mounted() {
    this.slider = new Swiper(this.$refs.slider, {
      pagination: {
        el: this.$refs.pagination,
        type: 'bullets',
        clickable: this.isClickableBullets,
      },
      navigation: {
        prevEl: this.topPositionArrow,
        nextEl: this.bottomPositionArrow,
      },
      breakpoints: this.breakpoints,
    })
    this.updateSlider()
    setTimeout(() => {
      this.updateSlider()
    }, 1000)
  },
  methods: {
    updateSlider() {
      Vue.nextTick(() => {
        setTimeout(() => {
          this.slider.update()
        }, 1000)
      })
    },
  },
  computed: {
    speakerPrefix() {
      return 'speaker_'
    },
    speakerSlots() {
      return createSlotsFor(this, this.speakerPrefix)
    },
    speakerEvents() {
      const {...allEvents} = createEventsFor(this, this.speakerPrefix)
      return allEvents
    },
    topPositionArrow() {
      return this.arrowPosition === 'top' ? this.$refs.btnPrevTop : this.$refs.btnPrevBottom
    },
    bottomPositionArrow() {
      return this.arrowPosition === 'top' ? this.$refs.btnNextTop : this.$refs.btnNextBottom
    },
  },
  watch: {
    speakers() {
      this.updateSlider()
    },
  },
}
</script>

<style lang="scss" scoped>
@import '/src/styles/mixins.scss';

.speaker-section {
  width: 100%;
  overflow: hidden;

  &__main-headline {
    font-size: var(--zeen-speaker-section-headline-size);
    color: var(--zeen-speaker-section-headline-color);
  }

  ::v-deep {
    .swiper-slide {
      height: auto;
      display: flex;
      flex-direction: column;
      box-sizing: border-box;
    }

    .swiper-container {
      overflow: visible;
      padding-bottom: var(--zeen-speaker-section-padding-bottom-swiper);
    }
  }

  &__swiper {
    @include tablets {
      padding-bottom: 40px;
    }
  }

  .swiper-pagination {
    text-align: var(--zeen-speaker-section-position-pagination);
  }

  .swiper-container-horizontal > .swiper-pagination-bullets,
  .swiper-pagination-custom,
  .swiper-pagination-fraction {
    bottom: 0;
  }

  ::v-deep.swiper-pagination-bullet {
    background-color: var(--zeen-speaker-section-bullet-color);
    opacity: initial;
    width: var(--zeen-speaker-section-size-bullet);
    height: var(--zeen-speaker-section-size-bullet);

    &-active {
      background-color: var(--zeen-speaker-section-bullet-active-color);
    }

    &:not(:last-child) {
      margin-right: var(--zeen-speaker-section-gap-bullet);
    }
  }

  .zeen-headline {
    margin: 0;
  }

  .speaker-card {
    ::v-deep.zeen-picture {
      display: block;

      &__img {
        max-width: 100% !important;
        width: 100%;
        max-height: initial !important;
      }
    }

    ::v-deep.zeen-headline {
      font-size: var(--zeen-speaker-section-headline-speaker-card);
    }
  }

  &__buttons-group {
    width: fit-content;
    display: flex;
    margin-left: auto;
    gap: var(--zeen-speaker-section-action-gap);

    &_bottom {
      margin-top: var(--zeen-speaker-section-action-bottom-margin-top);
    }
  }

  &__actions {
    margin-bottom: var(--zeen-speaker-section-action-margin-bottom);
    align-items: center;
  }

  .js-program {
    &-next {
      margin-left: auto;
    }

    &-btn {
      background-color: transparent;
      border: none;
      transform: rotate(180deg);
      cursor: pointer;
      transition-property: filter;
      transition-duration: 0.3s;
      transition-timing-function: ease;
      width: var(--zeen-speaker-section-action-btn-size);
      height: var(--zeen-speaker-section-action-btn-size);
      border-radius: var(--zeen-speaker-section-action-btn-border-radius);
      background-color: var(--gray-5);

      & svg {
        stroke: var(--zeen-speaker-section-arrow-main-color);
        fill: var(--zeen-speaker-section-arrow-main-color);
        transition-property: stroke, fill, filter;
        transition-duration: 0.3s;
        transition-timing-function: ease;
      }

      &:focus,
      &:visited {
        & svg {
          stroke: var(--zeen-speaker-section-arrow-main-color);
          fill: var(--zeen-speaker-section-arrow-main-color);
          filter: brightness(0.8);
        }
      }

      &:hover {
        & svg {
          stroke: var(--zeen-speaker-section-arrow-main-color);
          fill: var(--zeen-speaker-section-arrow-main-color);
          filter: brightness(0.8);
        }
      }

      &:active {
        & svg {
          stroke: var(--zeen-speaker-section-arrow-main-color);
          fill: var(--zeen-speaker-section-arrow-main-color);
          filter: brightness(0.6);
        }
      }
    }

    &-next {
      & svg {
        transform: rotate(180deg);
      }
    }

    &-swiper {
      overflow: visible;
    }

    &-actions {
      display: flex;
      justify-content: space-between;
    }
  }

  .swiper-button-disabled {
    cursor: default;

    & svg {
      stroke: var(--zeen-speaker-section-arrow-disabled-color);
      fill: var(--zeen-speaker-section-arrow-disabled-color);
    }

    &,
    &:focus,
    &:visited {
      & svg {
        stroke: var(--zeen-speaker-section-arrow-disabled-color);
        fill: var(--zeen-speaker-section-arrow-disabled-color);
      }
    }

    &:hover,
    &:active {
      & svg {
        stroke: var(--zeen-speaker-section-arrow-disabled-color);
        fill: var(--zeen-speaker-section-arrow-disabled-color);
        filter: none;
      }
    }
  }
}
</style>