<template>
  <div class="scroll-wrapper" ref="wrapper" :class="wrapperClasses">
    <slot></slot>
  </div>
</template>
<script lang="ts">
import {
  computed,
  defineComponent,
  onBeforeUnmount,
  onMounted,
  ref,
} from "vue";
import ScrollBar from "smooth-scrollbar";
export default defineComponent({
  props: {
    showTracks: {
      type: Boolean,
      default: true,
    },
    showShadow: {
      type: Boolean,
      default: true,
    },
  },
  setup({ showTracks, showShadow }) {
    const wrapper = ref<any>(null);
    const scrolledToTop = ref<boolean>(true);
    const scrolledToBottom = ref<boolean>(false);
    const scrollBar = ref<any>(null);

    const wrapperClasses = computed((): object => {
      return {
        top: scrolledToTop.value,
        bottom: scrolledToBottom.value,
        shadow: showShadow,
      };
    });

    onMounted((): void => {
      scrollBar.value = ScrollBar.init(wrapper.value as HTMLElement, {
        alwaysShowTracks: showTracks,
      });

      scrollBar.value.addListener(checkScrollPosition);
      checkScrollPosition();

      new window.ResizeObserver(() => {
        scrollBar.value.update();
        checkScrollPosition();
      }).observe(wrapper.value);
    });

    onBeforeUnmount((): void => {
      scrollBar.value.destroy();
    });

    const checkScrollPosition = (): void => {
      scrolledToBottom.value =
        scrollBar.value.offset.y >= scrollBar.value.limit.y ||
        (scrollBar.value.offset.y === 0 && !isFinite(scrollBar.value.limit.y));
      scrolledToTop.value = scrollBar.value.offset.y === 0;
    };

    return {
      wrapper,
      wrapperClasses,
    };
  },
});
</script>

<style lang="scss">
.scroll-wrapper {
  height: 100%;
  position: relative;

  &.hide-rail {
    .scrollbar-track-y {
      background-color: transparent;
    }
  }

  &.shrink-rail {
    .scrollbar-track-y {
      transform: scale3d(1, 0.9, 1) !important;
    }
  }

  &.top {
    &:before {
      opacity: 0;
    }
  }

  &.bottom {
    &:after {
      opacity: 0;
    }
  }

  &.shadow {
    &:after,
    &:before {
      content: "";
      background-image: linear-gradient(
        rgba(255, 255, 255, 0),
        rgba(255, 255, 255, 1)
      );
      position: absolute;
      left: 0;
      width: 100%;
      height: 80px;
      transition: opacity 0.3s ease;
      pointer-events: none;
      z-index: 1;
    }

    &:after {
      bottom: 0;
    }

    &:before {
      top: 0;
      transform: rotate(180deg);
      pointer-events: none;
    }
  }
}
</style>
