Skip to content

Commit 4ebc5b7

Browse files
fix(ui5-input): prevent typeahead during IME composition
1 parent 702150b commit 4ebc5b7

File tree

1 file changed

+46
-1
lines changed

1 file changed

+46
-1
lines changed

packages/main/src/Input.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ type InputSuggestionScrollEventDetail = {
161161
scrollContainer: HTMLElement;
162162
}
163163

164+
type CompositionEventHandler = (e?: CompositionEvent) => void;
165+
164166
/**
165167
* @class
166168
* ### Overview
@@ -606,6 +608,9 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
606608
})
607609
valueStateMessage!: Array<HTMLElement>;
608610

611+
_isComposing: boolean;
612+
_onCompositionStartBound: CompositionEventHandler;
613+
_onCompositionEndBound: CompositionEventHandler;
609614
hasSuggestionItemSelected: boolean;
610615
valueBeforeItemSelection: string;
611616
valueBeforeSelectionStart: string;
@@ -702,17 +707,57 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
702707
this._keepInnerValue = false;
703708
this._focusedAfterClear = false;
704709
this._valueStateLinks = [];
710+
711+
// Used to track if the user is composing text
712+
this._isComposing = false;
713+
714+
this._onCompositionStartBound = this._onCompositionStart.bind(this);
715+
this._onCompositionEndBound = this._onCompositionEnd.bind(this);
705716
}
706717

707718
onEnterDOM() {
708719
ResizeHandler.register(this, this._handleResizeBound);
709720
registerUI5Element(this, this._updateAssociatedLabelsTexts.bind(this));
721+
const input = this.nativeInput;
722+
if (input) {
723+
// Update to JSX bindings when Preact resolves bug with:
724+
// https://github.com/preactjs/preact/issues/1978
725+
input.addEventListener("compositionstart", this._onCompositionStartBound);
726+
input.addEventListener("compositionend", this._onCompositionEndBound);
727+
}
710728
}
711729

712730
onExitDOM() {
713731
ResizeHandler.deregister(this, this._handleResizeBound);
714732
deregisterUI5Element(this);
715733
this._removeLinksEventListeners();
734+
const input = this.nativeInput;
735+
if (input) {
736+
input.removeEventListener("compositionstart", this._onCompositionStartBound);
737+
input.removeEventListener("compositionend", this._onCompositionEndBound);
738+
}
739+
}
740+
741+
_onCompositionStart() {
742+
this._isComposing = true;
743+
}
744+
745+
_onCompositionEnd() {
746+
this._isComposing = false;
747+
requestAnimationFrame(() => {
748+
const value = this.value;
749+
if (!value) {
750+
return;
751+
}
752+
753+
if (!isAndroid() && !this._isKeyNavigation) {
754+
const item = this._getFirstMatchingItem(value);
755+
if (item) {
756+
this._handleTypeAhead(item);
757+
this._selectMatchingItem(item);
758+
}
759+
}
760+
});
716761
}
717762

718763
_highlightSuggestionItem(item: SuggestionItem) {
@@ -773,7 +818,7 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
773818

774819
// Typehead causes issues on Android devices, so we disable it for now
775820
// If there is already a selection the autocomplete has already been performed
776-
if (this._shouldAutocomplete && !isAndroid() && !autoCompletedChars && !this._isKeyNavigation) {
821+
if (this._shouldAutocomplete && !isAndroid() && !autoCompletedChars && !this._isKeyNavigation && !this._isComposing) {
777822
const item = this._getFirstMatchingItem(value);
778823
if (item) {
779824
this._handleTypeAhead(item);

0 commit comments

Comments
 (0)