<script>
  const galleryTrack = document.querySelector('.gallery .track');
  const galleryElements = document.querySelectorAll('.gallery .track > *');
  const galleryIndicator = document.querySelector('.gallery .indicator');
  const galleryPrevious = document.querySelector('.gallery button.prev');
  const galleryNext = document.querySelector('.gallery button.next');

  const next = () => {
    galleryTrack.scrollBy({
      left: galleryElements[0].scrollWidth,
      behavior: 'smooth'
    });
  };

  const prev = () => {
    galleryTrack.scrollBy({
      left: galleryElements[0].scrollWidth * -1,
      behavior: 'smooth'
    });
  };

  const progress = ({ target: { scrollLeft, scrollLeftMax } }) => {
    galleryIndicator.style.width = `${(scrollLeft / scrollLeftMax) * 100}%`;
  };

  const isAtEnd = () => {
    galleryTrack.scrollLeft === 0
      ? (galleryPrevious.disabled = true)
      : (galleryPrevious.disabled = false);
    galleryTrack.scrollLeft === galleryTrack.scrollLeftMax
      ? (galleryNext.disabled = true)
      : (galleryNext.disabled = false);
  };

  galleryPrevious.addEventListener('click', prev);
  galleryNext.addEventListener('click', next);
  galleryTrack.addEventListener('scroll', progress);
  galleryTrack.addEventListener('scroll', isAtEnd);
  document.addEventListener('DOMContentLoaded', isAtEnd);
</script>

<div class="gallery">
  <button class="prev"></button>
  <button class="next"></button>

  <div class="track">
    <slot></slot>
  </div>

  <div class="indicator"></div>
</div>

<style>
  .gallery {
    display: grid;
    grid-auto-columns: auto 1fr auto;
    grid-template-areas:
      'prev track next'
      '. progress .';
    align-items: center;
    gap: 1em;

    & .prev,
    & .next {
      position: relative;

      grid-row: track;

      font-size: 1.25em;
      color: var(--clr-text);

      cursor: pointer;

      background-color: var(--clr-box-background);

      border: var(--border-thin) solid var(--clr-text);
      border-radius: 100%;
      padding: 0.75em;

      z-index: 1;

      @media (min-width: 32em) {
        font-size: 1.25em;
      }

      &::after {
        position: absolute;
        inset: 0;
        align-content: center;
      }

      &:disabled {
        cursor: not-allowed;
        opacity: 0.5;
      }
    }

    & .prev {
      grid-column: prev;
      left: 0.5em;

      &::after {
        content: '«' / 'Previous';
      }
    }

    & .next {
      grid-column: next;
      right: 0.5em;

      &::after {
        content: '»' / 'Next';
      }
    }

    & .track {
      grid-row: track;
      grid-column: prev / next;
      display: grid;
      grid-auto-flow: column;
      grid-auto-columns: 100%;
      gap: 2em;

      overflow-x: auto;
      scroll-snap-type: x mandatory;
      scroll-behavior: smooth;
      scrollbar-width: none;

      & > * {
        margin-block: 0.25em 0;
        scroll-snap-align: center;
      }

      &::-webkit-scrollbar {
        display: none;
      }
    }

    & .ref-image img {
      width: 100%;
      height: 35em;
      object-fit: cover;
    }

    & .indicator {
      grid-row: track;
      grid-column: prev / next;
      place-self: start;

      height: 0.25em;
      width: 1em;
      min-width: 1em;

      background-color: var(--clr-gallery-indicator);

      z-index: 1;

      transition: width 0.4s ease-in-out 0.1s;
    }
  }
</style>
