Files
myprojplanet_vite/src/components/CMyImageGallery/CMyImageGallery.ts

60 lines
1.6 KiB
TypeScript
Executable File

import { defineComponent, ref, computed, type Ref } from 'vue';
export type GalleryImage = {
src: string;
alt?: string;
caption?: string;
};
export default defineComponent({
name: 'CMyImageGallery',
props: {
images: { type: Array as () => GalleryImage[], required: true },
layout: { type: String as () => 'grid' | 'carousel', default: 'grid' },
cols: { type: Number, default: 3 },
gap: { type: Number, default: 12 },
ratio: { type: Number, default: 1 },
lightbox: { type: Boolean, default: false }
},
emits: ['imageClick'],
setup(props, { emit }) {
const slide: Ref<number> = ref(0);
const lightboxOpen = ref(false);
const currentIndex = ref(0);
const gridStyle = computed(() => ({
gridTemplateColumns: `repeat(${props.cols}, 1fr)`,
gap: props.gap + 'px'
}));
const currentImage = computed(() => props.images?.[currentIndex.value] ?? null);
function onImageClick(idx: number) {
emit('imageClick', idx, props.images[idx]);
if (props.lightbox) {
currentIndex.value = idx;
lightboxOpen.value = true;
}
}
function next() {
if (!props.images?.length) return;
currentIndex.value = (currentIndex.value + 1) % props.images.length;
}
function prev() {
if (!props.images?.length) return;
currentIndex.value = (currentIndex.value - 1 + props.images.length) % props.images.length;
}
return {
slide,
lightboxOpen,
currentIndex,
currentImage,
gridStyle,
onImageClick,
next,
prev
};
}
});