<template>
  <transition :duration="resolvedDuration" mode="out-in" :name="formattedTransitionName" @after-enter="emit('onAfterEnter')">
    <slot />
  </transition>
</template>

<script setup lang="ts">
import { computed } from 'vue'

import { useReducedMotion } from '@/composables/useReducedMotion'

import { REDUCED_MOTION_FADE_MS } from '@/constants'

type Direction = 'forward' | 'backward'

type EmitType = {
  (event: 'onAfterEnter'): void
}

interface Props {
  direction?: Direction
  duration?: number
}

const props = withDefaults(defineProps<Props>(), {
  direction: 'forward',
  duration: 300,
})

const emit = defineEmits<EmitType>()

const formattedTransitionName = computed(() => `tab-content-${props.direction}`)

const prefersReducedMotion = useReducedMotion()
const resolvedDuration = computed(() => (prefersReducedMotion.value ? REDUCED_MOTION_FADE_MS : props.duration))
</script>

<style lang="scss">
.tab-content-backward,
.tab-content-forward {
  &-enter-active,
  &-leave-active {
    transition:
      transform 300ms ease,
      opacity 300ms ease;
  }

  &-enter-from,
  &-leave-to {
    opacity: 0;
  }

  &-enter-to {
    transform: translate3d(0, 0, 0);
  }
}

.tab-content-forward {
  &-enter-from {
    transform: translate3d(10vw, 0, 0);
  }

  &-leave-to {
    transform: translate3d(-10vw, 0, 0);
  }
}

.tab-content-backward {
  &-enter-from {
    transform: translate3d(-10vw, 0, 0);
  }

  &-leave-to {
    transform: translate3d(10vw, 0, 0);
  }
}
</style>
