Skip to content

Commit

Permalink
fix(drawer,dialog): detect click outside more precisely (#157)
Browse files Browse the repository at this point in the history
Co-authored-by: JD Solanki <[email protected]>
  • Loading branch information
IcetCode and jd-solanki authored Jun 12, 2023
1 parent 7a0a1b9 commit d6e181e
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 7 deletions.
7 changes: 4 additions & 3 deletions packages/anu-vue/src/components/dialog/ADialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ACard } from '@/components/card'
import { useDOMScrollLock } from '@/composables/useDOMScrollLock'
import { useDefaults } from '@/composables/useDefaults'
import { useTeleport } from '@/composables/useTeleport'
import { onClickSameTarget } from '@/composables/onClickSameTarget'
import { filterUsedSlots } from '@/utils/vue'
// SECTION Meta
Expand All @@ -24,8 +25,8 @@ const { props, defaultsClass, defaultsStyle, defaultsAttrs } = useDefaults(_prop
const { teleportTarget } = useTeleport()
const isMounted = useMounted()
const refCard = ref()
onClickOutside(refCard, () => {
const refMask = ref<HTMLDivElement>()
onClickSameTarget(refMask, () => {
// If dialog is open & persistent prop is false => Close dialog
if (props.modelValue && !props.persistent)
emit('update:modelValue', false)
Expand All @@ -44,12 +45,12 @@ useDOMScrollLock(toRef(props, 'modelValue') as Ref<boolean>)
<Transition name="bg">
<div
v-show="props.modelValue"
ref="refMask"
class="a-dialog-wrapper grid place-items-center fixed inset-0 bg-[hsla(var(--a-backdrop-c),var(--a-backdrop-opacity))]"
>
<Transition name="dialog">
<ACard
v-show="props.modelValue"
ref="refCard"
class="a-dialog backface-hidden transform translate-z-0 max-w-[calc(100vw-2rem)]"
:class="defaultsClass"
:style="defaultsStyle"
Expand Down
9 changes: 5 additions & 4 deletions packages/anu-vue/src/components/drawer/ADrawer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ACard } from '@/components/card'
import { useDOMScrollLock } from '@/composables/useDOMScrollLock'
import { useDefaults } from '@/composables/useDefaults'
import { useTeleport } from '@/composables/useTeleport'
import { onClickSameTarget } from '@/composables/onClickSameTarget'
import { filterUsedSlots } from '@/utils/vue'
// SECTION Meta
Expand All @@ -24,9 +25,9 @@ const { props, defaultsClass, defaultsStyle, defaultsAttrs } = useDefaults(_prop
const { teleportTarget } = useTeleport()
const isMounted = useMounted()
const refCard = ref()
onClickOutside(refCard, () => {
// If dialog is open & persistent prop is false => Close drawer
const refMask = ref<HTMLDivElement>()
onClickSameTarget(refMask, () => {
// If dialog is open & persistent prop is false => Close drawer
if (props.modelValue && !props.persistent)
emit('update:modelValue', false)
})
Expand Down Expand Up @@ -66,6 +67,7 @@ useDOMScrollLock(toRef(props, 'modelValue') as Ref<boolean>)
<Transition name="bg">
<div
v-show="props.modelValue"
ref="refMask"
v-bind="defaultsAttrs"
class="a-drawer-wrapper flex fixed inset-0 bg-[hsla(var(--a-backdrop-c),var(--a-backdrop-opacity))]"
:class="[
Expand All @@ -85,7 +87,6 @@ useDOMScrollLock(toRef(props, 'modelValue') as Ref<boolean>)
>
<ACard
v-show="props.modelValue"
ref="refCard"
:style="[`--${transitionName}-opacity: 1`, `--${transitionName}--transform-timing: ease-in-out`]"
class="a-drawer backface-hidden transform translate-z-0"
:class="transitionClasses"
Expand Down
32 changes: 32 additions & 0 deletions packages/anu-vue/src/composables/onClickSameTarget.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { MaybeElementRef } from '@vueuse/core'

export function onClickSameTarget(elRef: MaybeElementRef, handler: (e: MouseEvent) => void) {
let isMouseDownOnTarget = false
let isMouseUpOnTarget = false

// refer to this https://javascript.info/mouse-events-basics
// events fired in the order: mousedown -> mouseup -> click
const onClick = (e: MouseEvent) => {
if (isMouseDownOnTarget && isMouseUpOnTarget)
handler(e)

isMouseDownOnTarget = isMouseUpOnTarget = false
}

const onMousedown = (e: MouseEvent) => {
isMouseDownOnTarget = e.target === e.currentTarget
}
const onMouseup = (e: MouseEvent) => {
isMouseUpOnTarget = e.target === e.currentTarget
}

const cleanup = [
useEventListener(elRef as Element, 'click', onClick),
useEventListener(elRef as Element, 'mousedown', onMousedown),
useEventListener(elRef as Element, 'mouseup', onMouseup),
]

const stop = () => cleanup.forEach(fn => fn())

return stop
}

0 comments on commit d6e181e

Please sign in to comment.