Skip to content

Commit 7133cfe

Browse files
feat(onClickOutside): allow the value of target to be a getter (#5098)
1 parent 6c4294d commit 7133cfe

File tree

2 files changed

+44
-28
lines changed

2 files changed

+44
-28
lines changed

packages/core/onClickOutside/index.browser.test.ts

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import { describe, expect, it, vi } from 'vitest'
33
import { defineComponent, useTemplateRef } from 'vue'
44
import { onClickOutside } from './index'
55

6-
const complexComponent = defineComponent({
7-
template: `
6+
function getComplexComponent(useGetter = false) {
7+
return defineComponent({
8+
template: `
89
<div>
910
<div ref="target">
1011
Inside
@@ -23,31 +24,31 @@ const complexComponent = defineComponent({
2324
</div>
2425
</div>
2526
`,
26-
setup() {
27-
const target = useTemplateRef<HTMLDivElement>('target')
28-
const outside = useTemplateRef<HTMLDivElement>('outside')
27+
setup() {
28+
const target = useTemplateRef<HTMLDivElement>('target')
29+
const outside = useTemplateRef<HTMLDivElement>('outside')
30+
onClickOutside(
31+
useGetter ? () => target.value : target,
32+
(...args) => {
33+
console.log(...args)
34+
},
35+
{
36+
ignore: [outside],
37+
},
38+
)
2939

30-
onClickOutside(
31-
target,
32-
(...args) => {
33-
console.log(...args)
34-
},
35-
{
36-
ignore: [outside],
37-
},
38-
)
39-
40-
return {
41-
target,
42-
outside,
43-
}
44-
},
45-
})
40+
return {
41+
target,
42+
outside,
43+
}
44+
},
45+
})
46+
}
4647

4748
describe('onClickOutside', () => {
4849
it('should work with ignored element', async () => {
4950
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
50-
const screen = page.render(complexComponent)
51+
const screen = page.render(getComplexComponent())
5152
const target = screen.getByText('Inside')
5253
const outside = screen.getByText('Outside')
5354
const label = screen.getByText('Label')
@@ -63,4 +64,19 @@ describe('onClickOutside', () => {
6364
await userEvent.click(other)
6465
expect(consoleSpy).toHaveBeenCalled()
6566
})
67+
68+
it('allow the value of target to be a getter', async () => {
69+
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
70+
const screen = page.render(getComplexComponent(true))
71+
const target = screen.getByText('Inside')
72+
const other = screen.getByText('Other')
73+
74+
await expect.element(target).toBeInTheDocument()
75+
await expect.element(other).toBeInTheDocument()
76+
expect(consoleSpy).not.toHaveBeenCalled()
77+
await userEvent.click(target)
78+
expect(consoleSpy).not.toHaveBeenCalled()
79+
await userEvent.click(other)
80+
expect(consoleSpy).toHaveBeenCalled()
81+
})
6682
})

packages/core/onClickOutside/index.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Fn } from '@vueuse/shared'
22
import type { ComponentPublicInstance, MaybeRefOrGetter, VNode } from 'vue'
33
import type { ConfigurableWindow } from '../_configurable'
4-
import type { MaybeElementRef } from '../unrefElement'
4+
import type { MaybeComputedElementRef, MaybeElementRef } from '../unrefElement'
55
import { isIOS, noop } from '@vueuse/shared'
66
import { toValue } from 'vue'
77
import { defaultWindow } from '../_configurable'
@@ -58,22 +58,22 @@ let _iOSWorkaround = false
5858
export function onClickOutside<
5959
T extends OnClickOutsideOptions,
6060
>(
61-
target: MaybeElementRef,
61+
target: MaybeComputedElementRef,
6262
handler: OnClickOutsideHandler<T>,
6363
options?: T
6464
): Fn
6565

6666
export function onClickOutside<
6767
T extends OnClickOutsideOptions<true>,
6868
>(
69-
target: MaybeElementRef,
69+
target: MaybeComputedElementRef,
7070
handler: OnClickOutsideHandler<T>,
7171
options: T
7272
): OnClickOutsideControlsReturn
7373

7474
// Implementation
7575
export function onClickOutside(
76-
target: MaybeElementRef,
76+
target: MaybeComputedElementRef,
7777
handler: OnClickOutsideHandler,
7878
options: OnClickOutsideOptions<boolean> = {},
7979
) {
@@ -116,12 +116,12 @@ export function onClickOutside(
116116
* Determines if the given target has multiple root elements.
117117
* Referenced from: https://github.com/vuejs/test-utils/blob/ccb460be55f9f6be05ab708500a41ec8adf6f4bc/src/vue-wrapper.ts#L21
118118
*/
119-
function hasMultipleRoots(target: MaybeElementRef): boolean {
119+
function hasMultipleRoots(target: MaybeComputedElementRef): boolean {
120120
const vm = toValue(target) as ComponentPublicInstance
121121
return vm && vm.$.subTree.shapeFlag === 16
122122
}
123123

124-
function checkMultipleRoots(target: MaybeElementRef, event: Event): boolean {
124+
function checkMultipleRoots(target: MaybeComputedElementRef, event: Event): boolean {
125125
const vm = toValue(target) as ComponentPublicInstance
126126
const children = vm.$.subTree && vm.$.subTree.children
127127

0 commit comments

Comments
 (0)