Skip to content

Commit 8dcb5a9

Browse files
committed
Merge branch 'hotfix/lock-scroll' into next
1 parent 26cb524 commit 8dcb5a9

File tree

9 files changed

+73
-51
lines changed

9 files changed

+73
-51
lines changed

.github/ISSUE_TEMPLATE/-question.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,30 @@ assignees: hunterliu1003
88
---
99

1010
<!-- **IMPORTANT!**
11-
Please make sure to look for an answer to your question in our documentation and the documentation before asking a question here.
11+
Before reporting a bug, please make sure that you have read through our documentation and you think your problem is indeed an issue related to our module. -->
12+
13+
### Version
14+
15+
vue-final-modal: <!-- ex: v0.19.0 -->
16+
vue: <!-- ex: v2.6.12 -->
17+
nuxt: <!-- ex: v2.12.0 -->
18+
19+
### OS
20+
21+
Mac or Windows
22+
23+
### Reproduction Link
24+
<!--
25+
A minimal test case based on one of:
26+
- a fork of https://codesandbox.io/s/nuxtcontent-demo-l164h
27+
- a GitHub repository that can reproduce the bug
1228
-->
29+
30+
### Steps to reproduce
31+
32+
33+
### What is Expected?
34+
35+
36+
### What is actually happening?
37+

dist/VueFinalModal.esm.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/VueFinalModal.esm.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/VueFinalModal.umd.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/VueFinalModal.umd.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/content/en/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ Calculate `z-index` automatically with zIndexBase. If zIndex is set, `zIndexAuto
502502

503503
Set specific `z-index` to root of the modal element. If zIndex is set, `zIndexAuto`, `zIndexBase` will be ignored.
504504

505-
### `focusRemain`
505+
### `focusRetain`
506506

507507
- Type: `Boolean`
508508
- Default: `true`

lib/VueFinalModal.vue

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,7 @@
4141
tabindex="-1"
4242
@click.self="onClickContainer"
4343
>
44-
<div
45-
ref="vfmContent"
46-
class="vfm__content"
47-
:class="[contentClass, { 'vfm--prevent-auto': preventClick }]"
48-
:style="contentStyle"
49-
>
44+
<div class="vfm__content" :class="[contentClass, { 'vfm--prevent-auto': preventClick }]" :style="contentStyle">
5045
<slot :params="params" />
5146
</div>
5247
</div>
@@ -106,7 +101,6 @@ export default {
106101
setup(props, { emit }) {
107102
const uid = Symbol('vfm')
108103
const root = ref(null)
109-
const vfmContent = ref(null)
110104
const vfmContainer = ref(null)
111105
112106
const $vfm = inject(props.options.key)
@@ -196,7 +190,7 @@ export default {
196190
})
197191
onBeforeUnmount(() => {
198192
close()
199-
props.lockScroll && enableBodyScroll(vfmContent)
193+
props.lockScroll && enableBodyScroll(vfmContainer)
200194
root?.value?.remove()
201195
202196
let index = $vfm.modals.findIndex(vm => vm.uid === uid)
@@ -208,7 +202,6 @@ export default {
208202
props,
209203
emit,
210204
vfmContainer,
211-
vfmContent,
212205
getAttachElement,
213206
modalStackIndex,
214207
visibility,
@@ -279,11 +272,11 @@ export default {
279272
function handleLockScroll() {
280273
if (props.modelValue) {
281274
if (props.lockScroll) {
282-
disableBodyScroll(vfmContent, {
275+
disableBodyScroll(vfmContainer, {
283276
reserveScrollBarGap: true
284277
})
285278
} else {
286-
enableBodyScroll(vfmContent)
279+
enableBodyScroll(vfmContainer)
287280
}
288281
}
289282
}
@@ -348,7 +341,7 @@ export default {
348341
function afterModalLeave() {
349342
modalTransitionState.value = TransitionState.Leave
350343
modalStackIndex.value = null
351-
props.lockScroll && enableBodyScroll(vfmContent)
344+
props.lockScroll && enableBodyScroll(vfmContainer)
352345
353346
let stopEvent = false
354347
const event = createModalEvent({
@@ -403,7 +396,6 @@ export default {
403396
}
404397
return {
405398
root,
406-
vfmContent,
407399
vfmContainer,
408400
visible,
409401
visibility,

lib/utils/bodyScrollLock.js

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,47 @@ const isIosDevice =
2222

2323
let locks = []
2424
let documentListenerAdded = false
25+
let clientY = 0
2526
let initialClientY = -1
2627
let previousBodyOverflowSetting
2728
let previousBodyPaddingRight
2829

29-
// returns true if `el` should be allowed to receive touchmove events.
30-
const allowTouchMove = el =>
31-
locks.some(lock => {
32-
if (lock.options.allowTouchMove && lock.options.allowTouchMove(el)) {
33-
return true
34-
}
30+
const hasScrollbar = el => {
31+
if (!el || el.nodeType !== Node.ELEMENT_NODE) return false
3532

36-
return false
33+
const style = window.getComputedStyle(el)
34+
return ['auto', 'scroll'].includes(style.overflowY) && el.scrollHeight > el.clientHeight
35+
}
36+
37+
const shouldScroll = (el, delta) => {
38+
if (el.scrollTop === 0 && delta < 0) return false
39+
if (el.scrollTop + el.clientHeight + delta >= el.scrollHeight && delta > 0) return false
40+
return true
41+
}
42+
43+
const composedPath = el => {
44+
const path = []
45+
while (el) {
46+
path.push(el)
47+
if (el.classList.contains('vfm')) return path
48+
el = el.parentElement
49+
}
50+
return path
51+
}
52+
53+
const hasAnyScrollableEl = (el, delta) => {
54+
let hasAnyScrollableEl = false
55+
const path = composedPath(el)
56+
path.forEach(el => {
57+
if (hasScrollbar(el) && shouldScroll(el, delta)) {
58+
hasAnyScrollableEl = true
59+
}
3760
})
61+
return hasAnyScrollableEl
62+
}
63+
64+
// returns true if `el` should be allowed to receive touchmove events.
65+
const allowTouchMove = el => locks.some(() => hasAnyScrollableEl(el, -clientY))
3866

3967
const preventDefault = rawEvent => {
4068
const e = rawEvent || window.event
@@ -95,7 +123,7 @@ const isTargetElementTotallyScrolled = targetElement =>
95123
targetElement ? targetElement.scrollHeight - targetElement.scrollTop <= targetElement.clientHeight : false
96124

97125
const handleScroll = (event, targetElement) => {
98-
const clientY = event.targetTouches[0].clientY - initialClientY
126+
clientY = event.targetTouches[0].clientY - initialClientY
99127

100128
if (allowTouchMove(event.target)) {
101129
return false
@@ -160,27 +188,6 @@ export const disableBodyScroll = (targetElement, options) => {
160188
}
161189
}
162190

163-
export const clearAllBodyScrollLocks = () => {
164-
if (isIosDevice) {
165-
// Clear all locks ontouchstart/ontouchmove handlers, and the references.
166-
locks.forEach(lock => {
167-
lock.targetElement.ontouchstart = null
168-
lock.targetElement.ontouchmove = null
169-
})
170-
171-
if (documentListenerAdded) {
172-
document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined)
173-
documentListenerAdded = false
174-
}
175-
// Reset initial clientY.
176-
initialClientY = -1
177-
} else {
178-
restoreOverflowSetting()
179-
}
180-
181-
locks = []
182-
}
183-
184191
export const enableBodyScroll = targetElement => {
185192
if (!targetElement) {
186193
// eslint-disable-next-line no-console

types/index.d.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ interface VueFinalModalInfo {
1919
uid: symbol
2020
name: string
2121
emit: SetupContext<EmitsOptions>
22-
vfmContent: Ref<HTMLDivElement>
2322
getAttachElement(): false | HTMLElement
2423
modalStackIndex: Ref<number | null>
2524
visibility: {
@@ -32,8 +31,7 @@ interface VueFinalModalInfo {
3231
}
3332

3433
export type VueFinalModalComponent = ComponentPublicInstance & {
35-
vfmContainer: HTMLDivElement,
36-
vfmContent: HTMLDivElement
34+
vfmContainer: HTMLDivElement
3735
}
3836

3937
export type VueFinalModalProperty = {

0 commit comments

Comments
 (0)