Skip to content

Commit

Permalink
feat(useLockScroll): new function (#958)
Browse files Browse the repository at this point in the history
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
webfansplz and antfu committed Nov 24, 2021
1 parent 4e40c6f commit 930890a
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -7,7 +7,7 @@ Collection of essential Vue Composition Utilities
<a href="https://www.npmjs.com/package/@vueuse/core" target="__blank"><img src="https://img.shields.io/npm/v/@vueuse/core?color=a1b858&label=" alt="NPM version"></a>
<a href="https://www.npmjs.com/package/@vueuse/core" target="__blank"><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/@vueuse/core?color=50a36f&label="></a>
<a href="https://vueuse.org" target="__blank"><img src="https://img.shields.io/static/v1?label=&message=docs%20%26%20demos&color=1e8a7a" alt="Docs & Demos"></a>
<img alt="Function Count" src="https://img.shields.io/badge/-167%20functions-13708a">
<img alt="Function Count" src="https://img.shields.io/badge/-166%20functions-13708a">
<br>
<a href="https://github.com/vueuse/vueuse" target="__blank"><img alt="GitHub stars" src="https://img.shields.io/github/stars/vueuse/vueuse?style=social"></a>
</p>
Expand Down
1 change: 1 addition & 0 deletions packages/core/index.ts
Expand Up @@ -70,6 +70,7 @@ export * from './useRefHistory'
export * from './useResizeObserver'
export * from './useScriptTag'
export * from './useScroll'
export * from './useScrollLock'
export * from './useSessionStorage'
export * from './useShare'
export * from './useSpeechRecognition'
Expand Down
46 changes: 46 additions & 0 deletions packages/core/useScrollLock/demo.vue
@@ -0,0 +1,46 @@
<script setup lang="ts">
import { ref } from 'vue-demi'
import { useToggle } from '@vueuse/shared'
import { useScroll } from '../useScroll'
import { useScrollLock } from '.'
const el = ref<HTMLElement | null>(null)
useScroll(el)
const isLocked = useScrollLock(el)
const toggleLock = useToggle(isLocked)
</script>

<template>
<div class="flex flex-wrap">
<div ref="el" class="w-300px h-300px m-auto overflow-scroll bg-gray-500/5 rounded">
<div class="w-500px h-400px relative">
<div position="absolute left-0 top-0" bg="gray-500/5" p="x-2 y-1">
TopLeft
</div>
<div position="absolute left-0 bottom-0" bg="gray-500/5" p="x-2 y-1">
BottomLeft
</div>
<div position="absolute right-0 top-0" bg="gray-500/5" p="x-2 y-1">
TopRight
</div>
<div position="absolute right-0 bottom-0" bg="gray-500/5" p="x-2 y-1">
BottomRight
</div>
<div position="absolute left-1/3 top-1/3" bg="gray-500/5" p="x-2 y-1">
Scroll Me
</div>
</div>
</div>
<div class="m-auto px-6 py-4 rounded flex flex-col w-60 gap-2 bg-gray-500/5">
<div>
<span opacity="75">
isLocked
</span>
<BooleanDisplay :value="isLocked" />
</div>
<button opacity="75" @click="toggleLock()">
{{ isLocked ? 'Unlock' : 'Lock' }}
</button>
</div>
</div>
</template>
25 changes: 25 additions & 0 deletions packages/core/useScrollLock/index.md
@@ -0,0 +1,25 @@
---
category: Sensors
---

# useScrollLock

Lock scrolling of the element.

## Usage

```html
<script setup lang="ts">
import { useScrollLock } from '@vueuse/core'
const el = ref<HTMLElement | null>(null)
const isLocked = useScrollLock(el)
isLocked.value = true // lock
isLocked.value = false // unlock
</script>

<template>
<div ref="el"></div>
</template>
```
66 changes: 66 additions & 0 deletions packages/core/useScrollLock/index.ts
@@ -0,0 +1,66 @@
import { unref, ref, computed } from 'vue-demi'
import { MaybeRef, isClient, Fn } from '@vueuse/shared'
import { useEventListener } from '../useEventListener'

function preventDefault(rawEvent: TouchEvent): boolean {
const e = rawEvent || window.event
// Do not prevent if the event has more than one touch (usually meaning this is a multi touch gesture like pinch to zoom).
if (e.touches.length > 1) return true

if (e.preventDefault) e.preventDefault()

return false
}

// TODO: move to @vueuse/share
const isIOS = /* #__PURE__ */ isClient && window?.navigator && window?.navigator?.platform && /iP(ad|hone|od)/.test(window?.navigator?.platform)

/**
* Lock scrolling of the element.
*
* @see https://vueuse.org/useScrollLock
* @param element
*/
export function useScrollLock(
element: MaybeRef<HTMLElement | SVGElement | Window | Document | null | undefined>,
initialState = false,
) {
const isLocked = ref(initialState)
let touchMoveListener: Fn | null = null
let initialOverflow: CSSStyleDeclaration['overflow']

const lock = () => {
const ele = (unref(element) as HTMLElement)
if (!ele || isLocked.value) return
initialOverflow = ele.style.overflow
if (isIOS) {
touchMoveListener = useEventListener(
document,
'touchmove',
preventDefault,
{ passive: false },
)
}
else {
ele.style.overflow = 'hidden'
}
isLocked.value = true
}

const unlock = () => {
const ele = (unref(element) as HTMLElement)
if (!ele || !isLocked.value) return
isIOS ? touchMoveListener?.() : ele.style.overflow = initialOverflow
isLocked.value = false
}

return computed<boolean>({
get() {
return isLocked.value
},
set(v) {
if (v) lock()
else unlock()
},
})
}
1 change: 1 addition & 0 deletions packages/functions.md
Expand Up @@ -98,6 +98,7 @@
- [`usePointerSwipe`](https://vueuse.org/core/usePointerSwipe/) — reactive swipe detection based on [PointerEvents](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent)
- [`useResizeObserver`](https://vueuse.org/core/useResizeObserver/) — reports changes to the dimensions of an Element's content or the border-box
- [`useScroll`](https://vueuse.org/core/useScroll/) — reactive scroll position and state
- [`useScrollLock`](https://vueuse.org/core/useScrollLock/) — lock scrolling of the element
- [`useSpeechRecognition`](https://vueuse.org/core/useSpeechRecognition/) — reactive [SpeechRecognition](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition)
- [`useSpeechSynthesis`](https://vueuse.org/core/useSpeechSynthesis/) — reactive [SpeechSynthesis](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis)
- [`useSwipe`](https://vueuse.org/core/useSwipe/) — reactive swipe detection based on [`TouchEvents`](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent)
Expand Down

0 comments on commit 930890a

Please sign in to comment.