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'
4
7
import type { PhotoSwipePluginLocaleData } from '../../shared/index.js'
5
8
import { 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'
8
15
9
16
import 'photoswipe/dist/photoswipe.css'
10
17
import '../styles/photo-swipe.css'
@@ -15,57 +22,107 @@ export interface UsePhotoSwipeOptions extends PhotoSwipeBehaviorOptions {
15
22
string ,
16
23
Record < `${keyof PhotoSwipePluginLocaleData } Title`, string >
17
24
>
18
- /** @default 500 */
19
- delay ?: number
20
25
}
21
26
22
27
export const usePhotoSwipe = ( {
23
28
selector,
24
29
locales,
25
- delay = 500 ,
26
30
download = true ,
27
31
fullscreen = true ,
28
32
scrollToClose = true ,
29
33
} : UsePhotoSwipeOptions ) : void => {
30
34
const photoSwipeOptions = usePhotoSwipeOptions ( )
31
35
const locale = useLocaleConfig ( locales )
32
- const page = usePageData ( )
33
36
const frontmatter = usePageFrontmatter < { photoSwipe : boolean | string } > ( )
34
37
35
- let destroy : ( ( ) => void ) | null = null
36
-
37
- const setupPhotoSwipe = ( ) : void => {
38
+ const imageSelector = computed ( ( ) => {
38
39
const { photoSwipe } = frontmatter . value
39
40
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 )
53
113
} )
114
+ } )
115
+ }
54
116
}
55
117
56
118
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
+ } )
66
123
} )
67
124
68
125
onUnmounted ( ( ) => {
69
- destroy ?. ( )
126
+ photoSwipe ?. destroy ( )
70
127
} )
71
128
}
0 commit comments