Skip to content

Commit 569cec7

Browse files
authored
Fix change event incorrectly getting called on blur (#2296)
* drop `d.enqueue` & `d.workQueue` This was only used in tests and doesn't seem to be necessary. * drop `handleChange` from the `ComboboxInput` component This only emitted a `change` event, which Vue already emits as well. * drop `onChange` from incoming props This is an odd one. In Chrome this means that the `@change` is still being called, but if we keep it, then the `@change` is _also_ called on blur resulting in odd bugs. Droping it fixes that issue. That said, the `@change` is _still_ emitted and therefore the callback is properly called and the `ComboboxInput` still can interact with the `@change` event. * update changelog
1 parent b8c214e commit 569cec7

File tree

6 files changed

+14
-48
lines changed

6 files changed

+14
-48
lines changed

packages/@headlessui-react/src/test-utils/interactions.ts

+6-10
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,13 @@ export function shift(event: Partial<KeyboardEvent>) {
4141
export function word(input: string): Partial<KeyboardEvent>[] {
4242
let result = input.split('').map((key) => ({ key }))
4343

44-
d.enqueue(() => {
45-
let element = document.activeElement
44+
let element = document.activeElement
4645

47-
if (element instanceof HTMLInputElement) {
48-
fireEvent.change(element, {
49-
target: Object.assign({}, element, { value: input }),
50-
})
51-
}
52-
})
46+
if (element instanceof HTMLInputElement) {
47+
fireEvent.change(element, {
48+
target: Object.assign({}, element, { value: input }),
49+
})
50+
}
5351

5452
return result
5553
}
@@ -209,8 +207,6 @@ export async function type(events: Partial<KeyboardEvent>[], element = document.
209207
// We don't want to actually wait in our tests, so let's advance
210208
jest.runAllTimers()
211209

212-
await d.workQueue()
213-
214210
await new Promise(nextFrame)
215211
} catch (err) {
216212
if (err instanceof Error) Error.captureStackTrace(err, type)

packages/@headlessui-react/src/utils/disposables.ts

-11
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,8 @@ export type Disposables = ReturnType<typeof disposables>
44

55
export function disposables() {
66
let disposables: Function[] = []
7-
let queue: Function[] = []
87

98
let api = {
10-
enqueue(fn: Function) {
11-
queue.push(fn)
12-
},
13-
149
addEventListener<TEventName extends keyof WindowEventMap>(
1510
element: HTMLElement | Window | Document,
1611
name: TEventName,
@@ -66,12 +61,6 @@ export function disposables() {
6661
}
6762
},
6863

69-
async workQueue() {
70-
for (let handle of queue.splice(0)) {
71-
await handle()
72-
}
73-
},
74-
7564
style(node: HTMLElement, property: string, value: string) {
7665
let previous = node.style.getPropertyValue(property)
7766
Object.assign(node.style, { [property]: value })

packages/@headlessui-vue/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- Ensure the main tree and parent `Dialog` components are marked as `inert` ([#2290](https://github.com/tailwindlabs/headlessui/pull/2290))
1313
- Fix nested `Popover` components not opening ([#2293](https://github.com/tailwindlabs/headlessui/pull/2293))
14+
- Fix `change` event incorrectly getting called on `blur` ([#2296](https://github.com/tailwindlabs/headlessui/pull/2296))
1415

1516
## [1.7.10] - 2023-02-15
1617

packages/@headlessui-vue/src/components/combobox/combobox.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -888,10 +888,6 @@ export let ComboboxInput = defineComponent({
888888
}
889889
}
890890

891-
function handleChange(event: Event & { target: HTMLInputElement }) {
892-
emit('change', event)
893-
}
894-
895891
function handleInput(event: Event & { target: HTMLInputElement }) {
896892
api.openCombobox()
897893
emit('change', event)
@@ -914,7 +910,7 @@ export let ComboboxInput = defineComponent({
914910

915911
return () => {
916912
let slot = { open: api.comboboxState.value === ComboboxStates.Open }
917-
let { id, displayValue, ...theirProps } = props
913+
let { id, displayValue, onChange: _onChange, ...theirProps } = props
918914
let ourProps = {
919915
'aria-controls': api.optionsRef.value?.id,
920916
'aria-expanded': api.disabled.value
@@ -930,7 +926,6 @@ export let ComboboxInput = defineComponent({
930926
onCompositionstart: handleCompositionstart,
931927
onCompositionend: handleCompositionend,
932928
onKeydown: handleKeyDown,
933-
onChange: handleChange,
934929
onInput: handleInput,
935930
onBlur: handleBlur,
936931
role: 'combobox',

packages/@headlessui-vue/src/test-utils/interactions.ts

+6-10
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,13 @@ export function shift(event: Partial<KeyboardEvent>) {
3939
export function word(input: string): Partial<KeyboardEvent>[] {
4040
let result = input.split('').map((key) => ({ key }))
4141

42-
d.enqueue(() => {
43-
let element = document.activeElement
42+
let element = document.activeElement
4443

45-
if (element instanceof HTMLInputElement) {
46-
fireEvent.change(element, {
47-
target: Object.assign({}, element, { value: input }),
48-
})
49-
}
50-
})
44+
if (element instanceof HTMLInputElement) {
45+
fireEvent.change(element, {
46+
target: Object.assign({}, element, { value: input }),
47+
})
48+
}
5149

5250
return result
5351
}
@@ -207,8 +205,6 @@ export async function type(events: Partial<KeyboardEvent>[], element = document.
207205
// We don't want to actually wait in our tests, so let's advance
208206
jest.runAllTimers()
209207

210-
await d.workQueue()
211-
212208
await new Promise(nextFrame)
213209
} catch (err) {
214210
if (err instanceof Error) Error.captureStackTrace(err, type)

packages/@headlessui-vue/src/utils/disposables.ts

-11
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,8 @@ export type Disposables = ReturnType<typeof disposables>
22

33
export function disposables() {
44
let disposables: Function[] = []
5-
let queue: Function[] = []
65

76
let api = {
8-
enqueue(fn: Function) {
9-
queue.push(fn)
10-
},
11-
127
addEventListener<TEventName extends keyof WindowEventMap>(
138
element: HTMLElement | Window | Document,
149
name: TEventName,
@@ -52,12 +47,6 @@ export function disposables() {
5247
dispose()
5348
}
5449
},
55-
56-
async workQueue() {
57-
for (let handle of queue.splice(0)) {
58-
await handle()
59-
}
60-
},
6150
}
6251

6352
return api

0 commit comments

Comments
 (0)