1- import { isString , useLocaleConfig , wait } from '@vuepress/helper/client'
2- import { nextTick , onMounted , onUnmounted , watch } from 'vue'
3- import { usePageData , usePageFrontmatter } from 'vuepress/client'
1+ import { isArray , isString , useLocaleConfig } from '@vuepress/helper/client'
2+ import { useEventListener } from '@vueuse/core'
3+ import type PhotoSwipe from 'photoswipe'
4+ import type { SlideData } from 'photoswipe'
5+ import { computed , onMounted , onUnmounted } from 'vue'
6+ import { usePageFrontmatter } from 'vuepress/client'
47import type { PhotoSwipePluginLocaleData } from '../../shared/index.js'
58import { usePhotoSwipeOptions } from '../helpers/index.js'
6- import type { PhotoSwipeBehaviorOptions } from '../utils/index.js'
7- import { getImages , registerPhotoSwipe } from '../utils/index.js'
9+ import type { PhotoSwipeBehaviorOptions } from '../typings.js'
10+ import {
11+ LOADING_ICON ,
12+ resolveImageInfoFromElement ,
13+ setupPhotoSwipe ,
14+ } from '../utils/index.js'
815
916import 'photoswipe/dist/photoswipe.css'
1017import '../styles/photo-swipe.css'
@@ -15,57 +22,107 @@ export interface UsePhotoSwipeOptions extends PhotoSwipeBehaviorOptions {
1522 string ,
1623 Record < `${keyof PhotoSwipePluginLocaleData } Title`, string >
1724 >
18- /** @default 500 */
19- delay ?: number
2025}
2126
2227export const usePhotoSwipe = ( {
2328 selector,
2429 locales,
25- delay = 500 ,
2630 download = true ,
2731 fullscreen = true ,
2832 scrollToClose = true ,
2933} : UsePhotoSwipeOptions ) : void => {
3034 const photoSwipeOptions = usePhotoSwipeOptions ( )
3135 const locale = useLocaleConfig ( locales )
32- const page = usePageData ( )
3336 const frontmatter = usePageFrontmatter < { photoSwipe : boolean | string } > ( )
3437
35- let destroy : ( ( ) => void ) | null = null
36-
37- const setupPhotoSwipe = ( ) : void => {
38+ const imageSelector = computed ( ( ) => {
3839 const { photoSwipe } = frontmatter . value
3940
40- if ( photoSwipe !== false )
41- void nextTick ( )
42- . then ( ( ) => wait ( delay ) )
43- . then ( async ( ) => {
44- const imageSelector = isString ( photoSwipe ) ? photoSwipe : selector
45-
46- destroy = await registerPhotoSwipe ( getImages ( imageSelector ) , {
47- ...photoSwipeOptions . value ,
48- ...locale . value ,
49- download,
50- fullscreen,
51- scrollToClose,
52- } )
41+ return photoSwipe === false
42+ ? null
43+ : isString ( photoSwipe )
44+ ? photoSwipe
45+ : isArray ( selector )
46+ ? selector . join ( ', ' )
47+ : selector
48+ } )
49+
50+ const options = computed ( ( ) => ( {
51+ ...photoSwipeOptions . value ,
52+ ...locale . value ,
53+ download,
54+ fullscreen,
55+ scrollToClose,
56+ } ) )
57+
58+ let photoSwipeId = 0
59+ let photoSwipe : PhotoSwipe | null = null
60+
61+ const handlePhotoSwipe = async ( event : MouseEvent ) : Promise < void > => {
62+ const el = event . target as HTMLImageElement
63+
64+ if ( imageSelector . value && el . matches ( imageSelector . value ) ) {
65+ photoSwipe ?. destroy ( )
66+
67+ const { default : PhotoSwipe } = await import (
68+ /* webpackChunkName: "photo-swipe" */ 'photoswipe'
69+ )
70+
71+ const images = Array . from (
72+ document . querySelectorAll < HTMLImageElement > ( imageSelector . value ) ,
73+ )
74+ const currentIndex = images . findIndex ( ( image ) => image === el )
75+
76+ const dataSource = images . map < SlideData > ( ( image ) => ( {
77+ html : LOADING_ICON ,
78+ element : image ,
79+ msrc : image . src ,
80+ } ) )
81+
82+ dataSource . splice ( currentIndex , 1 , await resolveImageInfoFromElement ( el ) )
83+
84+ const id = Date . now ( )
85+
86+ photoSwipeId = id
87+ photoSwipe = new PhotoSwipe ( {
88+ preloaderDelay : 0 ,
89+ showHideAnimationType : 'zoom' ,
90+ ...options ,
91+ dataSource,
92+ index : currentIndex ,
93+ ...( scrollToClose
94+ ? { closeOnVerticalDrag : true , wheelToZoom : false }
95+ : { } ) ,
96+ } )
97+
98+ setupPhotoSwipe ( photoSwipe , { download, fullscreen } )
99+
100+ photoSwipe . init ( )
101+
102+ photoSwipe . on ( 'destroy' , ( ) => {
103+ photoSwipe = null
104+ photoSwipeId = 0
105+ } )
106+
107+ images . forEach ( ( image , index ) => {
108+ if ( index === currentIndex || photoSwipeId !== id ) return
109+
110+ void resolveImageInfoFromElement ( image ) . then ( ( data ) => {
111+ dataSource . splice ( index , 1 , data )
112+ photoSwipe ?. refreshSlideContent ( index )
53113 } )
114+ } )
115+ }
54116 }
55117
56118 onMounted ( ( ) => {
57- setupPhotoSwipe ( )
58-
59- watch (
60- ( ) => [ page . value . path , photoSwipeOptions . value ] ,
61- ( ) => {
62- destroy ?.( )
63- setupPhotoSwipe ( )
64- } ,
65- )
119+ useEventListener ( 'click' , handlePhotoSwipe )
120+ useEventListener ( 'wheel' , ( ) => {
121+ if ( options . value . scrollToClose ) photoSwipe ?. close ( )
122+ } )
66123 } )
67124
68125 onUnmounted ( ( ) => {
69- destroy ?. ( )
126+ photoSwipe ?. destroy ( )
70127 } )
71128}
0 commit comments