Vue Lightbox
Vue 3 के लिए फ़ुलस्क्रीन इमेज और वीडियो गैलरी lightbox, जो @reelkit/vue-lightbox पर बना है।
फ़ीचर
इंस्टॉलेशन
npm install @reelkit/vue-lightbox @reelkit/vue lucide-vue-nextstyles import करना न भूलें:
import '@reelkit/vue-lightbox/styles.css';आइकन
डिफ़ॉल्ट कंट्रोल आइकन के लिए lucide-vue-next इस्तेमाल करते हैं। अगर आप कोई और आइकन लाइब्रेरी पसंद करते हैं, तो अपने देने के लिए #controls और #navigation scoped slots इस्तेमाल करें।
क्विक स्टार्ट
stylesheet और LightboxOverlay कंपोनेंट import करें, फिर v-model:is-open से खोलना/बंद करना चलाएँ।
<script setup lang="ts">
import { ref } from 'vue';
import { LightboxOverlay, type LightboxItem } from '@reelkit/vue-lightbox';
import '@reelkit/vue-lightbox/styles.css';
const images: LightboxItem[] = [
{
src: '/cdn/samples/images/image-01.jpg',
title: 'Mountain River',
description: 'A beautiful mountain river',
},
{
src: '/cdn/samples/images/image-02.jpg',
title: 'Snowy Peaks',
},
{
src: '/cdn/samples/images/image-03.jpg',
title: 'Misty Forest',
description: 'Morning fog over the forest canopy',
},
{
src: '/cdn/samples/images/image-04.jpg',
title: 'Autumn Trail',
},
{
src: '/cdn/samples/images/image-05.jpg',
title: 'Ocean Cliff',
description: 'Dramatic cliffs above the Pacific',
},
{
src: '/cdn/samples/images/image-06.jpg',
title: 'Desert Dunes',
},
];
const open = ref(false);
const startIndex = ref(0);
function openAt(i: number) {
startIndex.value = i;
open.value = true;
}
</script>
<template>
<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:8px">
<button
v-for="(img, i) in images"
:key="img.src"
style="aspect-ratio:4/3;cursor:pointer"
@click="openAt(i)"
>
<img :src="img.src" style="width:100%;height:100%;object-fit:cover" />
</button>
</div>
<LightboxOverlay
v-model:is-open="open"
:items="images"
:initial-index="startIndex"
/>
</template>Scoped slots
छह नाम वाले scoped slots से overlay के हर हिस्से को पूरी तरह कस्टमाइज़ किया जा सकता है। बिल्ट-इन डिफ़ॉल्ट रखने के लिए slot छोड़ दें; उस हिस्से को पूरी तरह छिपाने के लिए slot के अंदर कुछ न दें (जैसे v-if="false" से)।
| Slot | Scope | विवरण |
|---|---|---|
| #slide | SlideSlotScope | अलग-अलग स्लाइड का कंटेंट बदलें (वीडियो स्लाइड के लिए ज़रूरी) |
| #controls | ControlsSlotScope | ऊपर का कंट्रोल बार बदलें (बंद, काउंटर, फ़ुलस्क्रीन) |
| #navigation | NavigationSlotScope | prev/next नेविगेशन तीर बदलें |
| #info | InfoSlotScope | नीचे का शीर्षक/विवरण gradient overlay बदलें |
| #loading | LoadingSlotScope | कस्टम लोडिंग इंडिकेटर |
| #error | ErrorSlotScope | कस्टम एरर इंडिकेटर |
<template>
<LightboxOverlay v-model:is-open="open" :items="items">
<!-- Custom info overlay -->
<template #info="{ item }">
<div class="my-caption">
<h2>{{ item.title }}</h2>
<p>{{ item.description }}</p>
</div>
</template>
<!-- Custom navigation -->
<template #navigation="{ onPrev, onNext, activeIndex, count }">
<div class="my-nav">
<button :disabled="activeIndex === 0" @click="onPrev">Prev</button>
<span>{{ activeIndex + 1 }} / {{ count }}</span>
<button :disabled="activeIndex === count - 1" @click="onNext">Next</button>
</div>
</template>
<!-- Custom controls -->
<template #controls="{ onClose, isFullscreen, onToggleFullscreen }">
<div class="my-controls">
<button @click="onToggleFullscreen">
{{ isFullscreen ? 'Exit Fullscreen' : 'Enter Fullscreen' }}
</button>
<button @click="onClose">Close</button>
</div>
</template>
</LightboxOverlay>
</template>वीडियो सपोर्ट
वीडियो स्लाइड opt-in हैं, ताकि डिफ़ॉल्ट बंडल ऑडियो/वीडियो की वायरिंग से मुक्त रहे। useVideoSlideRenderer(items) कॉल करें और लौटाए गए VideoSlideRenderer / VideoControlsRenderer को overlay के #slide और #controls slots में आगे भेजें। बिल्ट-इन साउंड टॉगल को context मिले, इसके लिए overlay को लौटाए गए SoundProvider में लपेटें। लौटाए गए ऑब्जेक्ट का टाइप UseVideoSlideRendererResult है: SoundProvider, hasVideo, VideoSlideRenderer और VideoControlsRenderer।
<script setup lang="ts">
import { ref } from 'vue';
import {
LightboxOverlay,
useVideoSlideRenderer,
type LightboxItem,
} from '@reelkit/vue-lightbox';
import '@reelkit/vue-lightbox/styles.css';
const open = ref(false);
const items: LightboxItem[] = [
{ src: '/image-01.jpg', title: 'Image' },
{
type: 'video',
src: '/clip.mp4',
poster: '/clip.jpg',
title: 'Clip',
},
];
const { VideoSlideRenderer, VideoControlsRenderer, SoundProvider } =
useVideoSlideRenderer(items);
</script>
<template>
<SoundProvider>
<LightboxOverlay v-model:is-open="open" :items="items">
<template #slide="scope">
<VideoSlideRenderer v-bind="scope" />
</template>
<template #controls="scope">
<VideoControlsRenderer v-bind="scope" />
</template>
</LightboxOverlay>
</SoundProvider>
</template>वीडियो स्लाइड चलाने वाला साझा <video> एलिमेंट वही पैटर्न इस्तेमाल करता है जो vue reel-player — iOS पर हर स्लाइड के लिए यूज़र जेस्चर माँगे बिना स्लाइड बदलने पर भी प्लेबैक चलता रहता है।
फ़ुलस्क्रीन
किसी जुड़े हुए एलिमेंट की फ़ुलस्क्रीन स्टेट देखने या टॉगल करने के लिए @reelkit/vue का useFullscreen इस्तेमाल करें। Lightbox अपना बिल्ट-इन फ़ुलस्क्रीन बटन इसी composable से चलाता है।
<script setup lang="ts">
import { shallowRef } from 'vue';
import { useFullscreen } from '@reelkit/vue';
const containerRef = shallowRef<HTMLDivElement | null>(null);
const { isFullscreen, toggle } = useFullscreen({ elementRef: containerRef });
</script>
<template>
<div ref="containerRef">
<button @click="toggle">
{{ isFullscreen.value ? 'Exit fullscreen' : 'Enter fullscreen' }}
</button>
</div>
</template>URL स्टेट
लाइव डेमो देखें →@reelkit/vue के useOverlayUrlState से कंट्रोलर बनाएँ और उसे LightboxUrlOverlay को controller के रूप में दें, तो गैलरी address bar के हाथ में आ जाती है: parameter किसी स्लाइड का नाम ले तो वह खुद खुलती है, और parameter हटते ही बंद हो जाती है। लिंक शेयर किए जा सकते हैं, और back बटन गैलरी बंद करता है। यह LightboxOverlay से अलग कंपोनेंट है, इसलिए हर एक में खुली स्टेट चलाने वाला ठीक एक स्रोत होता है — is-open model या url controller, कभी दोनों नहीं।
बिल्ट-इन keys
आप बिल्ट-इन key से स्लाइडों को पहचान सकते हैं — कंट्रोलर में urlIndexKey (स्थिति से) या urlStableIdKey (स्थिर id से) spread करें — दोनों @reelkit/vue से भी export होते हैं। URL स्टेट गाइड और Core API देखें।
Back सिर्फ़ तब बंद करता है जब आपने ऐप के अंदर से खोला हो — लिंक ने entry जोड़ी, इसलिए back गैलरी पर लौटता है। नए tab में सीधे खोले गए शेयर किए गए लिंक के पीछे कोई history नहीं होती, इसलिए ब्राउज़र का back साइट छोड़ देता है; बंद करने का बटन या Escape parameter को उसी जगह हटाकर आपको गैलरी पर रखता है।
<script setup lang="ts">
import { LightboxUrlOverlay, type LightboxItem } from '@reelkit/vue-lightbox';
import { useOverlayUrlState, urlIndexKey, urlStableIdKey } from '@reelkit/vue';
import '@reelkit/vue-lightbox/styles.css';
const props = defineProps<{ images: LightboxItem[] }>();
const photo = useOverlayUrlState({
param: 'photo',
...urlIndexKey(() => props.images.length),
});
</script>
<template>
<!-- Opening is a link — the href is the open action. No open flag, no
handler: the overlay reads the URL and opens itself. -->
<RouterLink v-for="(img, i) in props.images" :key="img.src" :to="`?photo=${i}`">
<img :src="img.src" />
</RouterLink>
<LightboxUrlOverlay :controller="photo" :items="props.images" />
</template>Composable विकल्पों का एक object लेता है और UrlStateController (set, index, value के साथ) लौटाता है। प्रोग्राम से नियंत्रण के लिए इसे रखें: set वह निचले स्तर का write है जो overlay अंदर से इस्तेमाल करता है (स्लाइड बदलना, और बंद करने के लिए set(null))। यह overlay को प्रोग्राम से भी चलाता है — set(index) उसे खोलता है, बिल्कुल parameter पर जाने की तरह। फ िर भी खोलने के लिए लिंक को प्राथमिकता दें: href शेयर किया जा सकता है, नए tab में खुलता है, और back बटन उसे बंद करता है — सब मुफ़्त में, बिना किसी हैंडलर के।
useOverlayUrlState के सारे विकल्प (param, adapter, codec, locator): Vue API रेफ़रेंस देखें।
LightboxUrlOverlay खुद सिर्फ़ :controller (ज़रूरी), एक @close emit, और LightboxOverlay के आगे भेजे जाने वाले सारे दिखावट और व्यवहार वाले props (items, transition-fn, scoped slots वगैरह) लेता है — लेकिन is-open नहीं।
- खोलने पर history की एक entry लगती है; स्लाइड बदलना उसे बदल देता है, इसलिए सौ स्वाइप भी कोई entry नहीं जोड़ते — back का एक कदम हमेशा गैलरी छोड़ देता है।
?photo=3जैसा शेयर किया गया लिंक गैलरी को उसी स्लाइड पर खोलता है। किसी स्लाइड का नाम न लेने वाला parameter, न खुल सकने वाली स्लाइड का दावा करने के बजाय URL से हटा दिया जाता है।
Routing वाले ऐप में adapter पास करें। history में सीधे लिखने से router की अपनी location पुरानी पड़ जाती है, और उसका अगला नेविगेशन parameter गिरा देता है।
<script setup lang="ts">
import { useVueRouterUrlAdapter } from '@reelkit/vue/vue-router-url-adapter';
const adapter = useVueRouterUrlAdapter();
const photo = useOverlayUrlState({
param: 'photo',
adapter,
...urlIndexKey(() => images.length),
});
</script>
<template>
<LightboxUrlOverlay :controller="photo" :items="images" />
</template>स्थिर लिंक। Index स्थिति पर आधारित है, इसलिए सूची का क्रम बदलते ही bookmark कोई दूसरी इमेज खोलता है। urlStableIdKey हर आइटम की स्थिर id से key बनाता है और मौजूदा सूची में ढूँढता है — आम मामले के लिए एक कॉल काफ़ी है।
<script setup lang="ts">
const photo = useOverlayUrlState({
param: 'photo',
...urlStableIdKey({ items: () => images }),
});
</script>
<template>
<LightboxUrlOverlay :controller="photo" :items="images" />
</template>URL में id को base64url में encode करने के लिए hashCodec: base64UrlCodec पास करें — वापस पढ़ा जा सकने वाला छिपाव, cryptographic hash नहीं।
किसी दूसरे field (slug) से key बनाएँ, या locateAsync से अनंत फ़ीड के पेज लोड करें, और codec/locator खुद बनाएँ: codec पहचान को URL में लिखता है, locator ढूँढता है कि वह अब कहाँ है।
<script setup lang="ts">
const photo = useOverlayUrlState({
param: 'photo',
codec: { decode: (raw) => raw, encode: (id) => id },
locator: {
locate: (id) => images.findIndex((x) => x.slug === id),
identify: (index) => images[index].slug,
},
});
</script>
<template>
<LightboxUrlOverlay :controller="photo" :items="images" />
</template>अनंत / पेज वाली गैलरी। locate synchronous है, इसलिए यह सिर्फ़ लोड हो चुके आइटम के लिए जवाब दे सकता है — जिस फ़ीड में 20 इमेज लोड हुई हैं, उसकी इमेज 400 का शेयर किया गया लिंक खाली लौटता है। locateAsync विकल्प है, जो सिर्फ़ न मिलने पर कॉल होता है: ज़रूरी पेज लोड करें, फिर वह index लौटाएँ जो पहचान का निकला।
छोटा रास्ता
आइटम की id से key बना रहे हैं? अपना codec और locator लिखना छोड़ें — locateAsync सीधे urlStableIdKey({ items, locateAsync }) को पास करें (न मिलने पर यह fetch करता है, फिर index लौटाता है)। नीचे का पूरा रूप किसी दूसरे field से key बनाने या पूरे नियंत्रण के लिए है।
<script setup lang="ts">
const photo = useOverlayUrlState({
param: 'photo',
codec: { decode: (raw) => raw, encode: (id) => id },
locator: {
locate: (id) => items.value.findIndex((x) => x.id === id),
identify: (index) => items.value[index].id,
locateAsync: async (id) => {
const loaded = await loadById(id); // or loadUntil(id) — fetch just that one, or page up to it
if (!loaded) return null; // exhausted — link names no item
items.value = loaded; // commit; the overlay renders from this
return loaded.findIndex((x) => x.id === id); // wherever it landed
},
},
});
</script>
<template>
<LightboxUrlOverlay :controller="photo" :items="items" />
</template>इसके pending रहने तक lightbox बंद रहता है और parameter को छुआ नहीं जाता, इसलिए सीधा लिंक fetch के बाद भी बना रहता है। null या rejection parameter हटा देता है। URL आगे बढ़ जाने, बंद होने या unmount के बाद आया जवाब फेंक दिया जाता है, इसलिए धीमा fetch ऐसी स्लाइड नहीं खोल सकता जो किसी ने माँगी ही नहीं। यह जो भी लौटाए, वही अंतिम है — यह अभी fetch किए डेटा का index बताता है, और lightbox items को दोबारा पढ़ने के बजाय उसे जैसा है वैसा लेता है, क्योंकि Vue ने उसे अभी दोबारा रेंडर नहीं किया है।
अपने-आप आगे बढ़ना
खुलते ही गैलरी को स्लाइडशो की तरह चलाने के लिए auto-advance सेट करें। यह डिफ़ॉल्ट रूप से बंद है, इसलिए मौजूदा lightbox पहले की तरह ही रेंडर होता और चलता है।
<script setup lang="ts">
import { ref } from 'vue';
import { LightboxOverlay, type LightboxApi } from '@reelkit/vue-lightbox';
const open = ref(false);
const lightbox = ref<LightboxApi | null>(null);
</script>
<template>
<LightboxOverlay
ref="lightbox"
v-model:is-open="open"
:items="items"
auto-advance
:auto-advance-interval="4000"
/>
<!-- The template ref drives it from outside: lightbox?.pause() -->
</template>- इमेज
auto-advance-interval(डिफ़ॉल्ट 5000 ms) तक रहती हैं, जो इमेज लोड होने के पल से गिना जाता है, इसलिए धीमी इमेज किसी के देखने से पहले कभी नहीं छूटती। जो इमेज लोड नहीं हो पाती, उसकी गिनती उसके error से होती है। - वीडियो loop की जगह एक बार चलते हैं और ख़त्म होने पर आगे बढ़ते हैं।
VideoSlideRendererयह आपके लिए करता है; कस्टम#slideअपने scope सेautoAdvanceपढ़ता है और अंत की सूचनाonEndedसे देता है। - यह रुका रहता है जब माउस किसी कंट्रोल (बटन, लिंक या कैप्शन) पर टिका हो, swipe के दौरान, और जब पेज छिपा हो, फिर वहीं से आगे चलता है जहाँ रुका था।
- हाथ से आगे बढ़ना (तीर, keys, wheel, swipe) नई स्लाइड का interval शून्य से शुरू करता है; स्लाइडशो चालू रहता है।
- आख़िरी स्लाइड पर यह रुक जाता है, जब तक
loopसेट न हो। कंट्रोल में play/pause बटन स्टेट दिखाता है और दर्शक को इसे बदलने देता है; LightboxApi परplay()औरpause()कोड से यही करते हैं।
कस्टम #controls slot को isAutoAdvancing मिलता है और, सिर्फ़ auto-advance चालू होने पर, onToggleAutoAdvance — जब यह मौजूद हो तो PlayPauseButton रेंडर करें। टाइमिंग ख़ुद @reelkit/core का createSlideshowController है; ऑटोप्ले गाइड और Core API देखें।
डाउनलोड
कंट्रोल में डाउनलोड बटन जोड़ने के लिए show-download सेट करें। यह सक्रिय आइटम को उसके downloadUrl से सेव करता है, जो न हो तो src से, उसके downloadName नाम से, जो न हो तो URL के आख़िरी हिस्से के नाम से।
<script setup lang="ts">
import { ref } from 'vue';
import {
CloseButton,
DownloadButton,
LightboxOverlay,
type LightboxItem,
} from '@reelkit/vue-lightbox';
const open = ref(false);
const items: LightboxItem[] = [
{
src: 'https://cdn.example.com/beach-1600.jpg',
// Save the original rather than the resized preview
downloadUrl: 'https://cdn.example.com/beach-original.jpg',
downloadName: 'beach.jpg',
},
];
</script>
<template>
<LightboxOverlay v-model:is-open="open" :items="items" show-download>
<!-- A custom bar shows the buttons only when their handler is there -->
<template #controls="{ onClose, isDownloading, onDownload }">
<DownloadButton
v-if="onDownload"
:is-downloading="isDownloading"
:on-press="onDownload"
/>
<CloseButton :on-press="onClose" />
</template>
</LightboxOverlay>
</template>फ़ाइल fetch करके सेव की जाती है, क्योंकि ब्राउज़र cross-origin लिंक पर download attribute को नज़रअंदाज़ करता है और फ़ाइल को खोल देता। जब fetch विफल हो — आम तौर पर दूसरे origin का ऐस ा सर्वर जो CORS headers नहीं भेजता — तो फ़ाइल नए टैब में खुलती है, जहाँ दर्शक उसे फिर भी सेव कर सकता है। एक क्लिक में सेव के लिए फ़ाइलें Access-Control-Allow-Origin के साथ serve करें। डाउनलोड चलते समय बटन disabled रहता है।
कस्टम #controls slot को isDownloading मिलता है और, सिर्फ़ show-download चालू होने पर, onDownload — जब यह मौजूद हो तो DownloadButton रेंडर करें। helper @reelkit/core का downloadFile है; डाउनलोड गाइड देखें।
कंट्रोल बटन
| कंपोनेंट | Props | विवरण |
|---|---|---|
PlayPauseButton | PlayPauseButtonProps: isPlaying, onPress, className? | स्लाइडशो टॉगल (Play/Pause आइकन, चलते समय aria-pressed)। auto-advance के साथ डिफ़ॉल्ट कंट्रोल इसे दिखाते हैं। |
DownloadButton | DownloadButtonProps: isDownloading, onPress, className? | डाउनलोड बटन, isDownloading के दौरान disabled। show-download के साथ डिफ़ॉल्ट कंट्रोल इसे दिखाते हैं। |
CloseButton | CloseButtonProps: onPress, className? | कंट्रोल बार का डिफ़ॉल्ट बंद करने का बटन; बिल्ट-इन रूप बनाए रखने के लिए इसे अपने #controls slot के अंदर रखें। |
Counter | CounterProps: currentIndex, count, className? | डिफ़ॉल्ट "3 / 10" काउंटर chip; बिल्ट-इन रूप बनाए रखने के लिए इसे अपने #controls slot के अंदर रखें। |
FullscreenButton | FullscreenButtonProps: isFullscreen, onPress, className? | डिफ़ॉल्ट फ़ुलस्क्रीन टॉगल; इसका आइकन isFullscreen के हिसाब से बदलता है। |
SoundButton | SoundButtonProps: isMuted, onPress, className? | वीडियो आइटम के लिए डिफ़ॉल्ट mute टॉगल; इसका आइकन isMuted के हिसाब से बदलता है। |
स्लाइड और नेविगेशन के हिस्से
| कंपोनेंट | Props | विवरण |
|---|---|---|
ImageSlide | ImageSlideProps: src, alt?, isActive, onReady?, onLoadError? | overlay की डिफ़ॉल्ट इमेज स्लाइड; इमेज आइटम के लिए बिल्ट-इन रूप बनाए रखने के लिए इसे अपने #slide slot के अंदर रखें। |
LightboxVideoSlide | LightboxVideoSlideProps: src, poster?, isActive, size, slideKey, loop?, onPlaying?, onWaiting?, onLoadError? | डिफ़ॉल्ट वीडियो स्लाइड, जो साझा <video> एलिमेंट से चलती है; useVideoSlideRenderer इसे आपके लिए रेंडर करता है। |
LightboxNavigation | LightboxNavigationProps: activeIndex, count, loop?, onPrev, onNext | डिफ़ॉल्ट पिछला/अगला तीर; बिल्ट-इन रूप बनाए रखने के लिए इसे अपने #navigation slot के अंदर रखें। |
API रेफ़रेंस
LightboxOverlay के props
LightboxOverlayProps
| Prop | टाइप | डिफ़ॉल्ट | वि वरण |
|---|---|---|---|
isOpen | boolean | ज़रूरी | दिखना नियंत्रित करता है; false होने पर overlay DOM से हट जाता है। v-model:is-open से bind किया जा सकता है। |
items | LightboxItem[] | ज़रूरी | आइटम (इमेज या वीडियो) का array |
initialIndex | number | 0 | शुरू में दिखने वाले आइटम का शून्य से शुरू होने वाला index |
transitionFn | TransitionTransformFn | slideTransition | स्लाइड ट्रांज़िशन फ़ंक्शन। कोई बिल्ट-इन (slideTransition, flipTransition, lightboxFadeTransition, lightboxZoomTransition) import करें या अपना पास करें। छोड़ने पर slideTransition लगता है। |
showInfo | boolean | true | शीर्षक/विवरण वाली जानकारी का overlay रेंडर करना है या नहीं |
showControls | boolean | true | ऊपर का कंट्रोल बार (बंद, काउंटर, फ़ुलस्क्रीन) रेंडर करना है या नहीं |
showNavigation | boolean | true | prev/next नेविगेशन तीर रेंडर करने हैं या नहीं (सिर्फ़ डेस्कटॉप) |
transitionDuration | number | 300 | ms में स्लाइड एनिमेशन की अवधि |
swipeDistanceFactor | number | 0.12 | स्लाइड बदलने के लिए स्वाइप दूरी का न्यूनतम हिस्सा (0–1) |
swipeToCloseDirection | 'up' | 'down' | 'up' | मोबाइल पर स्वाइप करके बंद करने वाले जेस्चर की दिशा |
loop | boolean | false | स्लाइडर आख़िरी स्लाइड से पहली पर लौटता है या नहीं |
enableNavKeys | boolean | true | कीबोर्ड की तीर वाली कुंजियों से नेविगेशन चालू करता है |
enableWheel | boolean | true | माउस व्हील से नेविगेशन चालू करता है |
wheelDebounceMs | number | 200 | ms में व्हील इवेंट के debounce की अवधि |
autoAdvance | boolean | false | गैलरी को स्लाइडशो की तरह चलाएँ। अपने-आप आगे बढ़ना देखें। |
autoAdvanceInterval | number | 5000 | स्लाइडशो के दौरान हर इमेज कितनी देर रहती है, ms में, लोड होने के बाद से गिना जाता है |
showDownload | boolean | false | सक्रिय आइटम के लिए डाउनलोड बटन जोड़ें। डाउनलोड देखें। |
ariaLabel | string | 'Image gallery' | dialog क्षेत्र का सुलभ लेबल |
LightboxUrlOverlay के props
LightboxUrlOverlayProps
ऊपर के सारे दिखावट और व्यवहार वाले props लेता है, सिवाय is-open के, जिसकी जगह controller आता है। यह close, slide-change और api-ready emit करता है, लेकिन update:is-open नहीं। यहाँ initial-index अनदेखा होता है — स्लाइड कंट्रोलर की स्थिति चुनती है, इसलिए साथ में दी गई value हर बार खुलने पर बदल दी जाती।
| Prop | टाइप | डिफ़ॉल्ट | विवरण |
|---|---|---|---|
controller | UrlStateController | ज़रूरी | useOverlayUrlState से मिला कंट्रोलर। इसकी स्थिति तय करती है कि overlay खुला है या नहीं और कौन-सी स्लाइड दिखती है; स्लाइड बदलने और बंद होने पर overlay इसी के ज़रिए वापस लिखता है। |
LightboxOverlay के इवेंट
| इवेंट | Payload | विवरण |
|---|---|---|
close | void | यूज़र के lightbox बंद करने पर emit होता है |
slide-change | number | बदलाव के बाद नए सक्रिय स्लाइड index के साथ emit होता है |
api-ready | LightboxApi | स्लाइडर तैयार होते ही एक बार emit होता है और imperative API देता है |
update:is-open | boolean | बंद होने पर emit होता है; v-model:is-open संभव बनाता है |
LightboxApi
वह ऑब्जेक्ट जो api-ready emit करता है, और जो कंपोनेंट की template ref पर भी मिलता है। स्लाइडर सिर्फ़ तब तक रहता है जब तक overlay खुला है, इसलिए बंद होने पर स्लाइडर का हर मेथड कुछ नहीं करता; close() हमेशा काम करता है।
| मेथड | टाइप | विवरण |
|---|---|---|
next() | () => void | एनिमेशन के साथ अगली slide पर जाता है। loop चालू न हो तो आख़िरी slide पर ही रुका रहता है। |
prev() | () => void | एनिमेशन के साथ पिछली slide पर जाता है। loop चालू न हो तो पहली slide पर ही रुका रहता है। |
goTo(index, animate?) | (number, boolean?) => Promise<void> | किसी slide पर कूदता है। index items की सीमा में रखा जाता है, animate डिफ़ॉल्ट रूप से false है। मूवमेंट पूरा होने पर resolve होता है। |
adjust() | () => void | ऐसे layout बदलाव के बाद slide की स्थिति फिर से निकालता है जिसे overlay ने खुद नहीं देखा |
observe() | () => void | unobserve() के बाद जेस्चर, कीबोर्ड और व्हील इनपुट फिर से सुनना शुरू करता है |
unobserve() | () => void | जेस्चर, कीबोर्ड और व्हील इनपुट सुनना बंद करता है; slides जहाँ हैं वहीं रहती हैं |
close() | () => void | lightbox बंद करता है, बंद बटन या Escape की तरह |
play() | () => void | स्लाइडशो शुरू करता है, सक्रिय स्लाइड को वहीं से आगे चलाते हुए जहाँ वह रुकी थी। auto-advance के बिना कुछ नहीं करता। |
pause() | () => void | स्लाइडशो रोकता है; सक्रिय स्लाइड अपनी प्रगति रखती है। auto-advance के बिना कुछ नहीं करता। |
LightboxItem इंटरफ़ेस
| Field | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
src | string | हाँ | इमेज या वीडियो का URL |
type | 'image' | 'video' | नहीं | आइटम का प्रकार। डिफ़ॉल्ट 'image' |
poster | string | नहीं | वीडियो आइटम की थंबनेल इमेज |
title | string | नहीं | जानकारी वाले overlay में दिखने वाला शीर्ष क |
description | string | नहीं | शीर्षक के नीचे दिखने वाला विवरण |
width | number | नहीं | पिक्सेल में इमेज की असली चौड़ाई |
height | number | नहीं | पिक्सेल में इमेज की असली ऊँचाई |
downloadUrl | string | नहीं | डाउनलोड बटन क्या सेव करता है। डिफ़ॉल्ट src |
downloadName | string | नहीं | किस फ़ाइल नाम से सेव करना है। डिफ़ॉल्ट URL के path का आख़िरी हिस्सा |
स्लॉट scope के टाइप
| टाइप | Fields |
|---|---|
SlideSlotScope | { item, index, size: [number, number], isActive, autoAdvance, onReady, onWaiting, onError, onEnded } |
ControlsSlotScope | { item, activeIndex, count, isFullscreen, isAutoAdvancing, isDownloading, onClose, onToggleFullscreen, onToggleAutoAdvance?, onDownload? } |
NavigationSlotScope | { item, activeIndex, count, onPrev, onNext } |
InfoSlotScope | { item, index } |
LoadingSlotScope | { item, activeIndex } |
ErrorSlotScope | { item, activeIndex } |
ट्रांज़िशन
transition-fn prop के ज़रि ए कोई भी TransitionTransformFn पास करें। सिर्फ़ इस्तेमाल होने वाला ट्रांज़िशन import करने से bundler बाकी को tree-shake कर देता है। छोड़ने पर slideTransition लगता है।
| फ़ंक्शन | विवरण |
|---|---|
slideTransition | डिफ़ॉल्ट। स्लाइडों के बीच हॉरिज़ॉन्टल खिसकाव; @reelkit/vue से भी export होता है। |
lightboxFadeTransition | हल्के हॉरिज़ॉन्टल झटके के साथ crossfade। @reelkit/vue-lightbox का अपना। |
flipTransition | Y-अक्ष के चारों ओर 3D flip; @reelkit/vue से भी export होता है। |
lightboxZoomTransition | आने वाली स्लाइड fade के साथ 70% → 100% बड़ी होती है। @reelkit/vue-lightbox का अपना। |
<script setup lang="ts">
import {
LightboxOverlay,
lightboxFadeTransition,
lightboxZoomTransition,
} from '@reelkit/vue-lightbox';
</script>
<template>
<!-- Built-in transition -->
<LightboxOverlay
v-model:is-open="open"
:items="items"
:transition-fn="lightboxFadeTransition"
/>
<!-- Different built-in -->
<LightboxOverlay
v-model:is-open="open"
:items="items"
:transition-fn="lightboxZoomTransition"
/>
</template>कंटेंट लोडिंग और एरर हैंडलिंग
जब आप #slide slot से रेंडरिंग अपने हाथ में लेते हैं, तो लोडिंग स्टेट बताने के लिए slot scope पर तीन lifecycle callbacks मिलते हैं। Lightbox हर स्लाइड की स्टेट ट्रैक करता है और उसके हिसाब से spinner या एरर आइकन दिखाता है। कंटेंट preloader टूटे URL cache करता है, इसलिए फ़ेल हुई स्लाइड पर दोबारा आने पर फिर से कोशिश नहीं होती।
Lifecycle callbacks
| Callback | टाइप | विवरण |
|---|---|---|
onReady | () => void | बताता है कि स्लाइड का कंटेंट सफलता से लोड हो गया (जैसे इमेज decode हुई) |
onWaiting | () => void | बताता है कि स्लाइड का कंटेंट लोड/buffer हो रहा है (spinner दिखाता है) |
onError | () => void | बताता है कि स्लाइड का कंटेंट लोड नहीं हुआ (एरर आइकन दिखाता है) |
#slide में callbacks जोड़ना
<template>
<LightboxOverlay v-model:is-open="open" :items="items">
<template
#slide="{ item, size, isActive, onReady, onWaiting, onError }"
>
<template v-if="item.type === 'video'">
<video
:src="item.src"
:poster="item.poster"
:autoplay="isActive"
:style="{ width: `${size[0]}px`, height: `${size[1]}px`, objectFit: 'contain' }"
@canplay="onReady"
@waiting="onWaiting"
@error="onError"
/>
</template>
<template v-else>
<img
:src="item.src"
:style="{ width: `${size[0]}px`, height: `${size[1]}px`, objectFit: 'contain' }"
@load="onReady"
@error="onError"
/>
</template>
</template>
</LightboxOverlay>
</template>कस्टम loading slot
डिफ़ॉल्ट spinner बदलने के लिए #loading slot इस्तेमाल करें।
<template>
<LightboxOverlay v-model:is-open="open" :items="items">
<template #loading="{ item, activeIndex }">
<div class="my-loading">
<span>Loading image {{ activeIndex + 1 }}…</span>
<span class="muted">{{ item.title }}</span>
</div>
</template>
</LightboxOverlay>
</template>कस्टम error slot
डिफ़ॉल्ट टूटी इमेज का आइकन बदलने के लिए #error slot इस्तेमाल करें।
<template>
<LightboxOverlay v-model:is-open="open" :items="items">
<template #error="{ item, activeIndex }">
<div class="my-error">
<span>Failed to load</span>
<span class="muted">{{ item.title ?? item.src }}</span>
</div>
</template>
</LightboxOverlay>
</template>CSS क्लास
सारी CSS क्लास साधारण हैं (scoped नहीं), इसलिए @reelkit/vue-lightbox/styles.css के बाद लोड होने वाली stylesheet में ज़्यादा specificity वाले selectors से इन्हें निशाना बनाया जा सकता है। रंग, आकार और z-index बदलने के लिए नीचे थीमिंग हिस्से में बताई CSS custom properties को प्राथमिकता दें।
| क्लास | कंपोनेंट | विवरण |
|---|---|---|
.rk-lightbox-overlay | Overlay | Root कंटेनर (फ़ुलस्क्रीन backdrop) |
.rk-lightbox-top-shade | Overlay | कंट्रोल के पीछे ऊपर का gradient |
.rk-lightbox-spinner | Overlay | डिफ़ॉल्ट लोडिंग spinner |
.rk-lightbox-error | Overlay | एरर स्टेट का कंटेनर (टूटी इमेज) |
.rk-lightbox-error-text | Overlay | एरर स्टेट का टेक्स्ट लेबल |
.rk-lightbox-controls-left | Controls | ऊपर-बाएँ कंट्रोल का कंटेनर |
.rk-lightbox-btn | Controls | कंट्रोल बटन (फ़ुलस्क्रीन, साउंड वगैरह) |
.rk-lightbox-play-pause | Controls | स्लाइडशो play/pause बटन (.rk-lightbox-btn के साथ) |
.rk-lightbox-download | Controls | डाउनलोड बटन (.rk-lightbox-btn के साथ) |
.rk-lightbox-close | Controls | बंद करने का बटन |
.rk-lightbox-counter | Controls | इमेज काउंटर chip |
.rk-lightbox-nav | Navigation | नेविगेशन तीर (prev और next दोनों) |
.rk-lightbox-nav-prev | Navigation | पिछला तीर |
.rk-lightbox-nav-next | Navigation | अगला तीर |
.rk-lightbox-info | Info | शीर्षक / विवरण का कंटेनर |
.rk-lightbox-info-title | Info | इमेज का शीर्षक |
.rk-lightbox-info-description | Info | इमेज का विवरण |
.rk-lightbox-slide | Slide | स्लाइड कंटेनर |
.rk-lightbox-img | Slide | इमेज एलिमेंट |
.rk-lightbox-video-container | VideoSlide | वीडियो स्लाइड कंटेनर (opt-in) |
.rk-lightbox-video-element | VideoSlide | वीडियो एलिमेंट (opt-in) |
.rk-lightbox-video-poster | VideoSlide | वीडियो की poster इमेज (opt-in) |
थीमिंग
थीम बदलने के लिए :root (या .rk-lightbox-overlay के किसी भी ancestor) पर कोई भी --rk-lightbox-* CSS custom property override करें। .rk-lightbox-overlay पर सीधे लिखी declarations विरासत में मिली values को ढक देंगी, इसलिए overrides किसी ancestor selector पर रखें।
| Token | डिफ़ॉल्ट | क्या नियंत्रित करता है |
|---|---|---|
--rk-lightbox-overlay-bg | #000 | Backdrop का रंग |
--rk-lightbox-overlay-z | 9999 | Overlay का z-index |
--rk-lightbox-top-shade-height | 80px | ऊपर के gradient की ऊँचाई |
--rk-lightbox-top-shade-bg | linear-gradient(rgba(0,0,0,0.6), transparent) | ऊपर का gradient |
--rk-lightbox-edge-padding | 16px | बंद / नेविगेशन / कंट्रोल की किनारे से दूरी |
--rk-lightbox-btn-bg | rgba(0, 0, 0, 0.5) | बंद / नेविगेशन / छोटे बटन का डिफ़ॉल्ट background |
--rk-lightbox-btn-bg-hover | rgba(255, 255, 255, 0.2) | बंद / नेविगेशन / छोटे बटन का hover background |
--rk-lightbox-btn-fg | #fff | बंद / नेविगेशन / छोटे बटन के आइकन का रंग |
--rk-lightbox-btn-size | 36px | छोटे बटन का आकार (फ़ुलस्क्रीन टॉगल वगैरह) |
--rk-lightbox-btn-disabled-opacity | 0.5 | disabled छोटे बटन की opacity (डाउनलोड चलते समय) |
--rk-lightbox-close-size | 40px | बंद करने के बटन का आकार |
--rk-lightbox-nav-size | 48px | prev / next तीर का आकार |
--rk-lightbox-nav-opacity | 0.7 | आराम की हालत में prev / next तीरों की opacity |
--rk-lightbox-counter-bg | rgba(0, 0, 0, 0.5) | काउंटर chip का background |
--rk-lightbox-counter-fg | #fff | काउंटर के टेक्स्ट का रंग |
--rk-lightbox-info-bg | linear-gradient(transparent, rgba(0,0,0,0.8)) | कैप्शन के पीछे का gradient |
--rk-lightbox-title-size | 18px | शीर्षक का font size |
--rk-lightbox-description-size | 14px | विवरण का font size |
--rk-lightbox-video-bg | #000 | <video> के पीछे letterbox background |
<style>
:root {
--rk-lightbox-overlay-bg: #0f172a;
--rk-lightbox-btn-bg: rgba(99, 102, 241, 0.65);
--rk-lightbox-btn-bg-hover: rgba(168, 85, 247, 0.85);
--rk-lightbox-info-bg: linear-gradient(
transparent,
rgba(99, 102, 241, 0.55) 60%,
rgba(168, 85, 247, 0.85)
);
}
</style>सुलभता
Overlay का root एक modal dialog है (role="dialog", aria-modal="true")। स्क्रीन रीडर की घोषणा बदलने के लिए aria-label prop सेट करें; डिफ़ॉल्ट "Image gallery" है। हर स्लाइड पर role="group", aria-roledescription="slide" और स्थिति से बना aria-label होता है (जैसे "Image 2 of 5")।
Lightbox खुलने पर फ़ोकस पकड़ता है और बंद होने पर उसे trigger पर लौटा देता है। Tab और Shift+Tab अंदर के फ़ोकस होने वाले एलिमेंट में घूमते हैं; बाहर निकला फ़ोकस (बाहर क्लिक, प्रोग्राम से फ़ोकस) वापस खींच लिया जाता है। यह @reelkit/vue के captureFocusForReturn और createFocusTrap से बना है।
कीबोर्ड शॉर्टकट
| कुंजी | क्रिया |
|---|---|
ArrowLeft | पिछली इमेज |
ArrowRight | अगली इमेज |
Escape | lightbox बंद करें (या चालू हो तो फ़ुलस्क्रीन से बाहर आएँ) |