Correctly handle IME composition in <Combobox.Input> (#2426)

* Don’t try to open combobox when composing characters

* wip

* Delay IME composition end until after keydown events

* Use `d.nextFrame` to handle `compositionend` event

* Update changelog
This commit is contained in:
Jordan Pittman
2023-04-17 10:17:28 -04:00
committed by GitHub
parent 35367453a8
commit b98e642a67
4 changed files with 27 additions and 2 deletions
+1
View File
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix `className` hydration for `<Transition appear>` ([#2390](https://github.com/tailwindlabs/headlessui/pull/2390))
- Improve `Combobox` types to improve false positives ([#2411](https://github.com/tailwindlabs/headlessui/pull/2411))
- Merge `className` correctly when its a function ([#2412](https://github.com/tailwindlabs/headlessui/pull/2412))
- Correctly handle IME composition in `<Combobox.Input>` ([#2426](https://github.com/tailwindlabs/headlessui/pull/2426))
### Added
@@ -821,12 +821,19 @@ function InputFn<
)
let isComposing = useRef(false)
let composedChangeEvent = useRef<React.ChangeEvent<HTMLInputElement> | null>(null)
let handleCompositionStart = useEvent(() => {
isComposing.current = true
})
let handleCompositionEnd = useEvent(() => {
setTimeout(() => {
d.nextFrame(() => {
isComposing.current = false
if (composedChangeEvent.current) {
actions.openCombobox()
onChange?.(composedChangeEvent.current)
composedChangeEvent.current = null
}
})
})
@@ -953,6 +960,10 @@ function InputFn<
})
let handleChange = useEvent((event: React.ChangeEvent<HTMLInputElement>) => {
if (isComposing.current) {
composedChangeEvent.current = event
return
}
actions.openCombobox()
onChange?.(event)
})
+1
View File
@@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `FocusTrap` event listeners once document has loaded ([#2389](https://github.com/tailwindlabs/headlessui/pull/2389))
- Don't scroll-lock `<Dialog>` when wrapping transition isn't showing ([#2422](https://github.com/tailwindlabs/headlessui/pull/2422))
- Ensure DOM `ref` is properly handled in the `RadioGroup` component ([#2424](https://github.com/tailwindlabs/headlessui/pull/2424))
- Correctly handle IME composition in `<Combobox.Input>` ([#2426](https://github.com/tailwindlabs/headlessui/pull/2426))
### Added
@@ -37,6 +37,7 @@ import { objectToFormEntries } from '../../utils/form'
import { useControllable } from '../../hooks/use-controllable'
import { useTrackedPointer } from '../../hooks/use-tracked-pointer'
import { isMobile } from '../../utils/platform'
import { disposables } from '../../utils/disposables'
function defaultComparator<T>(a: T, z: T): boolean {
return a === z
@@ -763,12 +764,19 @@ export let ComboboxInput = defineComponent({
})
let isComposing = ref(false)
let composedChangeEvent = ref<(Event & { target: HTMLInputElement }) | null>(null)
function handleCompositionstart() {
isComposing.value = true
}
function handleCompositionend() {
setTimeout(() => {
disposables().nextFrame(() => {
isComposing.value = false
if (composedChangeEvent.value) {
api.openCombobox()
emit('change', composedChangeEvent.value)
composedChangeEvent.value = null
}
})
}
@@ -891,6 +899,10 @@ export let ComboboxInput = defineComponent({
}
function handleInput(event: Event & { target: HTMLInputElement }) {
if (isComposing.value) {
composedChangeEvent.value = event
return
}
api.openCombobox()
emit('change', event)
}