Skip to content

Commit bfb1208

Browse files
committed
✨ Add destroy to popover
1 parent bd29062 commit bfb1208

3 files changed

Lines changed: 140 additions & 2 deletions

File tree

scripts/utilityTypes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ export type PopoverPosition = 'top'
107107
108108
export type PopoverInstance = {
109109
close: () => void
110+
destroy: () => void
110111
remove: () => void
111112
}
112113

src/tests/unit/popover.test.ts

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ describe('popover', () => {
3030
vi.restoreAllMocks()
3131
})
3232

33+
it('should return undefined if trigger or popover does not exist', () => {
34+
const instance = popover({
35+
trigger: '#missing',
36+
popover: '#popover'
37+
})
38+
39+
expect(instance).toBeUndefined()
40+
})
41+
3342
it('should position and show the popover on trigger click', () => {
3443
const onOpen = vi.fn()
3544

@@ -51,6 +60,130 @@ describe('popover', () => {
5160
position: 'bottom'
5261
})
5362
})
63+
64+
it('should close popover using instance.close()', () => {
65+
const onClose = vi.fn()
66+
const instance = popover({
67+
trigger: '#trigger',
68+
popover: '#popover',
69+
onClose
70+
})!
71+
72+
triggerElement.click()
73+
instance.close()
74+
75+
popoverElement.dispatchEvent(
76+
new TransitionEvent('transitionend', { bubbles: true })
77+
)
78+
79+
expect(popoverElement.dataset.show).toBe(undefined)
80+
expect(onClose).toHaveBeenCalledWith({
81+
trigger: triggerElement,
82+
popover: popoverElement,
83+
position: 'bottom'
84+
})
85+
})
86+
87+
it('should remove click listener on destroy()', () => {
88+
const instance = popover({
89+
trigger: '#trigger',
90+
popover: '#popover'
91+
})!
92+
93+
instance.destroy()
94+
triggerElement.click()
95+
96+
expect(popoverElement.dataset.show).toBe('')
97+
})
98+
99+
it('should remove popover DOM on remove()', () => {
100+
const instance = popover({
101+
trigger: '#trigger',
102+
popover: '#popover'
103+
})!
104+
105+
instance.remove()
106+
107+
expect(document.getElementById('popover')).toBeNull()
108+
})
109+
110+
it('should close when clicking outside if closeOnBlur is true', () => {
111+
popover({
112+
trigger: '#trigger',
113+
popover: '#popover',
114+
closeOnBlur: true
115+
})
116+
117+
triggerElement.click()
118+
document.body.click()
119+
120+
expect(popoverElement.dataset.show).toBe(undefined)
121+
})
122+
123+
it('should close when pressing Escape if closeOnEsc is true', () => {
124+
popover({
125+
trigger: '#trigger',
126+
popover: '#popover',
127+
closeOnEsc: true
128+
})
129+
130+
triggerElement.click()
131+
132+
document.dispatchEvent(
133+
new KeyboardEvent('keydown', { key: 'Escape' })
134+
)
135+
136+
expect(popoverElement.dataset.show).toBe(undefined)
137+
})
138+
139+
it('should not close on blur if closeOnBlur is false', () => {
140+
popover({
141+
trigger: '#trigger',
142+
popover: '#popover',
143+
closeOnBlur: false
144+
})
145+
146+
triggerElement.click()
147+
document.body.click()
148+
149+
expect(popoverElement.dataset.show).toBe('true')
150+
})
151+
152+
it('should flip position when overflowing viewport', () => {
153+
vi.spyOn(triggerElement, 'getBoundingClientRect').mockReturnValue({
154+
top: window.innerHeight - 10,
155+
left: 0,
156+
width: 100,
157+
height: 50,
158+
bottom: 0,
159+
right: 0,
160+
x: 0,
161+
y: 0,
162+
toJSON: () => {}
163+
} as DOMRect)
164+
165+
vi.spyOn(popoverElement, 'getBoundingClientRect').mockReturnValue({
166+
width: 200,
167+
height: 200,
168+
top: 0,
169+
left: 0,
170+
bottom: 0,
171+
right: 0,
172+
x: 0,
173+
y: 0,
174+
toJSON: () => {}
175+
} as DOMRect)
176+
177+
popover({
178+
trigger: '#trigger',
179+
popover: '#popover',
180+
position: 'bottom'
181+
})
182+
183+
triggerElement.click()
184+
185+
expect(popoverElement.dataset.position).toBe('top')
186+
})
54187
})
55188

56189
describe('closePopover', () => {

src/utils/popover.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export type PopoverPosition = 'top'
1616

1717
export type PopoverInstance = {
1818
close: () => void
19+
destroy: () => void
1920
remove: () => void
2021
}
2122

@@ -266,8 +267,7 @@ export const popover = ({
266267
close() {
267268
closePopover()
268269
},
269-
remove() {
270-
popoverDOM.remove()
270+
destroy() {
271271
triggerDOM.removeEventListener('click', handleOpen)
272272
observer.disconnect()
273273

@@ -278,6 +278,10 @@ export const popover = ({
278278
if (closeOnEsc) {
279279
document.removeEventListener('keydown', handleCloseOnEsc)
280280
}
281+
},
282+
remove() {
283+
popoverDOM.remove()
284+
this.destroy()
281285
}
282286
}
283287
}

0 commit comments

Comments
 (0)