Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(photo-swipe)!: rebuild photo-swipe plugin #303

Merged
merged 6 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 0 additions & 40 deletions docs/plugins/features/photo-swipe.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,6 @@ In preview mode, you can:
- Default: `true`
- Details: Whether close the current image when scrolling.

### delay

- Type: `number`
- Default: `800`
- Details:

The delay of operating dom, in ms.

::: tip

If the theme you are using has a switching animation, it is recommended to configure this option to `Switch animation duration + 200`.

:::

### locales

- Type: `PhotoSwipePluginLocaleConfig`
Expand Down Expand Up @@ -254,32 +240,6 @@ onUnmounted(() => {
</template>
```

`registerPhotoSwipe` allows you to register photoswipe for the given image elements:

```vue
<script setup lang="ts">
import { registerPhotoSwipe } from '@vuepress/plugin-photo-swipe/client'
import { onMounted, onUnmounted } from 'vue'

let destroy: () => null | void = null

onMounted(async () => {
await nextTick()

const images = Array.from(document.querySelectorAll('img'))

// create a new photoswipe instance on image elements
destroy = await registerPhotoSwipe(images, {
// photoswipe options
})
})

onUnmounted(() => {
destroy?.()
})
</script>
```

## Styles

You can customize the style via CSS variables:
Expand Down
40 changes: 0 additions & 40 deletions docs/zh/plugins/features/photo-swipe.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,6 @@ export default {
- 默认值:`true`
- 详情:是否在滚动时关闭当前图片。

### delay

- 类型:`number`
- 默认值:`800`
- 详情:

操作页面 DOM 的延时,单位 ms。

::: tip

如果你使用的主题有切换动画,建议配置此选项为 `切换动画时长 + 200`。

:::

### locales

- 类型:`PhotoSwipePluginLocaleConfig`
Expand Down Expand Up @@ -254,32 +240,6 @@ onUnmounted(() => {
</template>
```

`registerPhotoSwipe` 允许你为给定的图片元素注册 photoswipe:

```vue
<script setup lang="ts">
import { registerPhotoSwipe } from '@vuepress/plugin-photo-swipe/client'
import { onMounted, onUnmounted } from 'vue'

let destroy: () => null | void = null

onMounted(async () => {
await nextTick()

const images = Array.from(document.querySelectorAll('img'))

// 通过图片元素创建一个新的 photoswipe 实例
destroy = await registerPhotoSwipe(images, {
// photoswipe 选项
})
})

onUnmounted(() => {
destroy?.()
})
</script>
```

## 样式

你可以通过 CSS 变量来自定义部分样式:
Expand Down
3 changes: 3 additions & 0 deletions e2e/docs/.vuepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { catalogPlugin } from '@vuepress/plugin-catalog'
import { copyrightPlugin } from '@vuepress/plugin-copyright'
import { feedPlugin } from '@vuepress/plugin-feed'
import { noticePlugin } from '@vuepress/plugin-notice'
import { photoSwipePlugin } from '@vuepress/plugin-photo-swipe'
import { pwaPlugin } from '@vuepress/plugin-pwa'
import { redirectPlugin } from '@vuepress/plugin-redirect'
import { registerComponentsPlugin } from '@vuepress/plugin-register-components'
Expand Down Expand Up @@ -98,6 +99,7 @@ export default defineUserConfig({
},

themePlugins: {
mediumZoom: false,
sitemap: {
devServer: true,
devHostname: 'https://ecosystem-e2e-test.com',
Expand Down Expand Up @@ -256,6 +258,7 @@ export default defineUserConfig({
},
],
}),
photoSwipePlugin(),
pwaPlugin({
manifest: {
icons: [
Expand Down
6 changes: 6 additions & 0 deletions e2e/docs/photo-swipe/disabled.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
photoSwipe: false
---

![](/logo.png)
![](/favicon.ico)
2 changes: 2 additions & 0 deletions e2e/docs/photo-swipe/enabled.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
![](/logo.png)
![](/favicon.ico)
1 change: 1 addition & 0 deletions e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@vuepress/plugin-copyright": "workspace:*",
"@vuepress/plugin-feed": "workspace:*",
"@vuepress/plugin-notice": "workspace:*",
"@vuepress/plugin-photo-swipe": "workspace:*",
"@vuepress/plugin-pwa": "workspace:*",
"@vuepress/plugin-redirect": "workspace:*",
"@vuepress/plugin-register-components": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { isString, useLocaleConfig, wait } from '@vuepress/helper/client'
import { nextTick, onMounted, onUnmounted, watch } from 'vue'
import { usePageData, usePageFrontmatter } from 'vuepress/client'
import { isArray, isString, useLocaleConfig } from '@vuepress/helper/client'
import { useEventListener } from '@vueuse/core'
import type PhotoSwipe from 'photoswipe'
import type { SlideData } from 'photoswipe'
import { computed, onMounted, onUnmounted } from 'vue'
import { usePageFrontmatter } from 'vuepress/client'
import type { PhotoSwipePluginLocaleData } from '../../shared/index.js'
import { usePhotoSwipeOptions } from '../helpers/index.js'
import type { PhotoSwipeBehaviorOptions } from '../utils/index.js'
import { getImages, registerPhotoSwipe } from '../utils/index.js'
import type { PhotoSwipeBehaviorOptions } from '../typings.js'
import {
LOADING_ICON,
resolveImageInfoFromElement,
setupPhotoSwipe,
} from '../utils/index.js'

import 'photoswipe/dist/photoswipe.css'
import '../styles/photo-swipe.css'
Expand All @@ -15,57 +22,107 @@ export interface UsePhotoSwipeOptions extends PhotoSwipeBehaviorOptions {
string,
Record<`${keyof PhotoSwipePluginLocaleData}Title`, string>
>
/** @default 500 */
delay?: number
}

export const usePhotoSwipe = ({
selector,
locales,
delay = 500,
download = true,
fullscreen = true,
scrollToClose = true,
}: UsePhotoSwipeOptions): void => {
const photoSwipeOptions = usePhotoSwipeOptions()
const locale = useLocaleConfig(locales)
const page = usePageData()
const frontmatter = usePageFrontmatter<{ photoSwipe: boolean | string }>()

let destroy: (() => void) | null = null

const setupPhotoSwipe = (): void => {
const imageSelector = computed(() => {
const { photoSwipe } = frontmatter.value

if (photoSwipe !== false)
void nextTick()
.then(() => wait(delay))
.then(async () => {
const imageSelector = isString(photoSwipe) ? photoSwipe : selector

destroy = await registerPhotoSwipe(getImages(imageSelector), {
...photoSwipeOptions.value,
...locale.value,
download,
fullscreen,
scrollToClose,
})
return photoSwipe === false
? null
: isString(photoSwipe)
? photoSwipe
: isArray(selector)
? selector.join(', ')
: selector
})

const options = computed(() => ({
...photoSwipeOptions.value,
...locale.value,
download,
fullscreen,
scrollToClose,
}))

let photoSwipeId = 0
let photoSwipe: PhotoSwipe | null = null

const handlePhotoSwipe = async (event: MouseEvent): Promise<void> => {
const el = event.target as HTMLImageElement

if (imageSelector.value && el.matches(imageSelector.value)) {
photoSwipe?.destroy()

const { default: PhotoSwipe } = await import(
/* webpackChunkName: "photo-swipe" */ 'photoswipe'
)

const images = Array.from(
document.querySelectorAll<HTMLImageElement>(imageSelector.value),
)
const currentIndex = images.findIndex((image) => image === el)

const dataSource = images.map<SlideData>((image) => ({
html: LOADING_ICON,
element: image,
msrc: image.src,
}))

dataSource.splice(currentIndex, 1, await resolveImageInfoFromElement(el))

const id = Date.now()

photoSwipeId = id
photoSwipe = new PhotoSwipe({
preloaderDelay: 0,
showHideAnimationType: 'zoom',
...options,
dataSource,
index: currentIndex,
...(scrollToClose
? { closeOnVerticalDrag: true, wheelToZoom: false }
: {}),
})

setupPhotoSwipe(photoSwipe, { download, fullscreen })

photoSwipe.init()

photoSwipe.on('destroy', () => {
photoSwipe = null
photoSwipeId = 0
})

images.forEach((image, index) => {
if (index === currentIndex || photoSwipeId !== id) return

void resolveImageInfoFromElement(image).then((data) => {
dataSource.splice(index, 1, data)
photoSwipe?.refreshSlideContent(index)
})
})
}
}

onMounted(() => {
setupPhotoSwipe()

watch(
() => [page.value.path, photoSwipeOptions.value],
() => {
destroy?.()
setupPhotoSwipe()
},
)
useEventListener('click', handlePhotoSwipe)
useEventListener('wheel', () => {
if (options.value.scrollToClose) photoSwipe?.close()
})
})

onUnmounted(() => {
destroy?.()
photoSwipe?.destroy()
})
}
3 changes: 0 additions & 3 deletions plugins/features/plugin-photo-swipe/src/client/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { injectPhotoSwipeConfig } from './helpers/index.js'
import './styles/vars.css'

declare const __PS_SELECTOR__: string[] | string
declare const __PS_DELAY__: number
declare const __PS_LOCALES__: Record<
string,
Record<`${keyof PhotoSwipePluginLocaleData}Title`, string>
Expand All @@ -17,7 +16,6 @@ declare const __PS_SCROLL_TO_CLOSE__: boolean

const selector = __PS_SELECTOR__
const locales = __PS_LOCALES__
const delay = __PS_DELAY__
const download = __PS_DOWNLOAD__
const fullscreen = __PS_FULLSCREEN__
const scrollToClose = __PS_SCROLL_TO_CLOSE__
Expand All @@ -29,7 +27,6 @@ export default defineClientConfig({
setup: () => {
usePhotoSwipe({
selector,
delay,
locales,
download,
fullscreen,
Expand Down
3 changes: 2 additions & 1 deletion plugins/features/plugin-photo-swipe/src/client/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './helpers/index.js'
export * from './composables/index.js'
export * from './utils/index.js'
export type * from './typings.js'
export { createPhotoSwipe } from './utils/index.js'
export type * from '../shared/index.js'
Loading
Loading