Skip to content

Commit d6e181e

Browse files
IcetCodejd-solanki
andauthored
fix(drawer,dialog): detect click outside more precisely (#157)
Co-authored-by: JD Solanki <jdsolanki0001@gmail.com>
1 parent 7a0a1b9 commit d6e181e

File tree

3 files changed

+41
-7
lines changed

3 files changed

+41
-7
lines changed

packages/anu-vue/src/components/dialog/ADialog.vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { ACard } from '@/components/card'
66
import { useDOMScrollLock } from '@/composables/useDOMScrollLock'
77
import { useDefaults } from '@/composables/useDefaults'
88
import { useTeleport } from '@/composables/useTeleport'
9+
import { onClickSameTarget } from '@/composables/onClickSameTarget'
910
import { filterUsedSlots } from '@/utils/vue'
1011
1112
// SECTION Meta
@@ -24,8 +25,8 @@ const { props, defaultsClass, defaultsStyle, defaultsAttrs } = useDefaults(_prop
2425
const { teleportTarget } = useTeleport()
2526
const isMounted = useMounted()
2627
27-
const refCard = ref()
28-
onClickOutside(refCard, () => {
28+
const refMask = ref<HTMLDivElement>()
29+
onClickSameTarget(refMask, () => {
2930
// If dialog is open & persistent prop is false => Close dialog
3031
if (props.modelValue && !props.persistent)
3132
emit('update:modelValue', false)
@@ -44,12 +45,12 @@ useDOMScrollLock(toRef(props, 'modelValue') as Ref<boolean>)
4445
<Transition name="bg">
4546
<div
4647
v-show="props.modelValue"
48+
ref="refMask"
4749
class="a-dialog-wrapper grid place-items-center fixed inset-0 bg-[hsla(var(--a-backdrop-c),var(--a-backdrop-opacity))]"
4850
>
4951
<Transition name="dialog">
5052
<ACard
5153
v-show="props.modelValue"
52-
ref="refCard"
5354
class="a-dialog backface-hidden transform translate-z-0 max-w-[calc(100vw-2rem)]"
5455
:class="defaultsClass"
5556
:style="defaultsStyle"

packages/anu-vue/src/components/drawer/ADrawer.vue

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { ACard } from '@/components/card'
66
import { useDOMScrollLock } from '@/composables/useDOMScrollLock'
77
import { useDefaults } from '@/composables/useDefaults'
88
import { useTeleport } from '@/composables/useTeleport'
9+
import { onClickSameTarget } from '@/composables/onClickSameTarget'
910
import { filterUsedSlots } from '@/utils/vue'
1011
1112
// SECTION Meta
@@ -24,9 +25,9 @@ const { props, defaultsClass, defaultsStyle, defaultsAttrs } = useDefaults(_prop
2425
const { teleportTarget } = useTeleport()
2526
const isMounted = useMounted()
2627
27-
const refCard = ref()
28-
onClickOutside(refCard, () => {
29-
// If dialog is open & persistent prop is false => Close drawer
28+
const refMask = ref<HTMLDivElement>()
29+
onClickSameTarget(refMask, () => {
30+
// If dialog is open & persistent prop is false => Close drawer
3031
if (props.modelValue && !props.persistent)
3132
emit('update:modelValue', false)
3233
})
@@ -66,6 +67,7 @@ useDOMScrollLock(toRef(props, 'modelValue') as Ref<boolean>)
6667
<Transition name="bg">
6768
<div
6869
v-show="props.modelValue"
70+
ref="refMask"
6971
v-bind="defaultsAttrs"
7072
class="a-drawer-wrapper flex fixed inset-0 bg-[hsla(var(--a-backdrop-c),var(--a-backdrop-opacity))]"
7173
:class="[
@@ -85,7 +87,6 @@ useDOMScrollLock(toRef(props, 'modelValue') as Ref<boolean>)
8587
>
8688
<ACard
8789
v-show="props.modelValue"
88-
ref="refCard"
8990
:style="[`--${transitionName}-opacity: 1`, `--${transitionName}--transform-timing: ease-in-out`]"
9091
class="a-drawer backface-hidden transform translate-z-0"
9192
:class="transitionClasses"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import type { MaybeElementRef } from '@vueuse/core'
2+
3+
export function onClickSameTarget(elRef: MaybeElementRef, handler: (e: MouseEvent) => void) {
4+
let isMouseDownOnTarget = false
5+
let isMouseUpOnTarget = false
6+
7+
// refer to this https://javascript.info/mouse-events-basics
8+
// events fired in the order: mousedown -> mouseup -> click
9+
const onClick = (e: MouseEvent) => {
10+
if (isMouseDownOnTarget && isMouseUpOnTarget)
11+
handler(e)
12+
13+
isMouseDownOnTarget = isMouseUpOnTarget = false
14+
}
15+
16+
const onMousedown = (e: MouseEvent) => {
17+
isMouseDownOnTarget = e.target === e.currentTarget
18+
}
19+
const onMouseup = (e: MouseEvent) => {
20+
isMouseUpOnTarget = e.target === e.currentTarget
21+
}
22+
23+
const cleanup = [
24+
useEventListener(elRef as Element, 'click', onClick),
25+
useEventListener(elRef as Element, 'mousedown', onMousedown),
26+
useEventListener(elRef as Element, 'mouseup', onMouseup),
27+
]
28+
29+
const stop = () => cleanup.forEach(fn => fn())
30+
31+
return stop
32+
}

0 commit comments

Comments
 (0)