Shuunen/folio

View on GitHub
components/photo-gallery.vue

Summary

Maintainability
Test Coverage
<script setup lang="ts">
import lightGallery from 'lightgallery'
import { onMounted, ref } from 'vue'
import type { Photo } from '../data/types'

defineProps<{
  nbToShow?: number
  photos: Photo[]
}>()

const wrapper = ref<HTMLElement>()

function initLightGallery () {
  if (!wrapper.value) throw new Error('no wrapper found for lightgallery')
  lightGallery(wrapper.value, {
    thumbnail: true, // eslint-disable-line @typescript-eslint/naming-convention
    licenseKey: 'B71019E7-24F2485D-9D04849F-4F8C909F',
  })
}

function guessThumb (source: string) {
  // eslint-disable-next-line regexp/no-super-linear-move
  return source.replace(/(?<name>.+)\.(?=(?:gif|jpg|png)$)/u, '$<name>-thumb.')
}

onMounted(initLightGallery)
</script>

<template>
  <div ref="wrapper" class="app-photo-gallery not-prose flex flex-wrap gap-4">
    <!-- eslint-disable sonar/no-vue-bypass-sanitization -->
    <a v-for="{ label, src, size, thumb }, index in photos" :key="`photo-${index}`" class="overflow-hidden"
      :class="[nbToShow && nbToShow <= index ? 'hidden' : '']" :data-lg-size="size" :href="src">
      <img :alt="label" class="h-60 object-cover transition-transform duration-1000 hover:scale-110" :src="thumb ?? guessThumb(src)" />
    </a>
  </div>
</template>

<!-- eslint-disable-next-line vue-scoped-css/enforce-style-type, vue/enforce-style-attribute -->
<style>
@import url("lightgallery/css/lightgallery.css");
@import url("lightgallery/css/lg-thumbnail.css");
@import url("lightgallery/css/lg-zoom.css");
@import url("lightgallery/css/lg-video.css");
</style>