diff --git a/.changeset/nine-icons-end.md b/.changeset/nine-icons-end.md new file mode 100644 index 000000000..31cef53ca --- /dev/null +++ b/.changeset/nine-icons-end.md @@ -0,0 +1,5 @@ +--- +'@lion/ui': patch +--- + +Fix search issues when modifying the middle of the input word in LionCombobox. diff --git a/packages/ui/components/combobox/src/LionCombobox.js b/packages/ui/components/combobox/src/LionCombobox.js index a93e0922a..8e9b28112 100644 --- a/packages/ui/components/combobox/src/LionCombobox.js +++ b/packages/ui/components/combobox/src/LionCombobox.js @@ -849,7 +849,9 @@ export class LionCombobox extends LocalizeMixin(OverlayMixin(LionListbox)) { * @protected */ _handleAutocompletion() { - const hasSelection = this._inputNode.value.length !== this._inputNode.selectionStart; + const isSelectionEmpty = this._inputNode.selectionStart === this._inputNode.selectionEnd; + const hasSelection = + !isSelectionEmpty && this._inputNode.value.length !== this._inputNode.selectionStart; const inputValue = this._inputNode.value; const inputSelectionStart = this._inputNode.selectionStart; diff --git a/packages/ui/components/combobox/test-helpers/combobox-helpers.js b/packages/ui/components/combobox/test-helpers/combobox-helpers.js index 89fc0da67..b4594c5b1 100644 --- a/packages/ui/components/combobox/test-helpers/combobox-helpers.js +++ b/packages/ui/components/combobox/test-helpers/combobox-helpers.js @@ -63,39 +63,33 @@ export function mimicKeyPress(el, key) { export async function mimicUserTypingAdvanced(el, values) { const { _inputNode } = getComboboxMembers(el); _inputNode.dispatchEvent(new Event('focusin', { bubbles: true })); + let cursorPosition = _inputNode.selectionStart || 0; for (const key of values) { // eslint-disable-next-line no-await-in-loop, no-loop-func await new Promise(resolve => { - const hasSelection = _inputNode.selectionStart !== _inputNode.selectionEnd; + const selectionStart = _inputNode.selectionStart || 0; + const selectionEnd = _inputNode.selectionEnd || 0; + const hasSelection = selectionStart !== selectionEnd; if (key === 'Backspace') { if (hasSelection) { _inputNode.value = - _inputNode.value.slice( - 0, - _inputNode.selectionStart ? _inputNode.selectionStart : undefined, - ) + - _inputNode.value.slice( - _inputNode.selectionEnd ? _inputNode.selectionEnd : undefined, - _inputNode.value.length, - ); - } else { - _inputNode.value = _inputNode.value.slice(0, -1); + _inputNode.value.slice(0, selectionStart) + _inputNode.value.slice(selectionEnd); + cursorPosition = selectionStart; + } else if (cursorPosition > 0) { + _inputNode.value = + _inputNode.value.slice(0, cursorPosition - 1) + _inputNode.value.slice(cursorPosition); + cursorPosition -= 1; } } else if (hasSelection) { _inputNode.value = - _inputNode.value.slice( - 0, - _inputNode.selectionStart ? _inputNode.selectionStart : undefined, - ) + - key + - _inputNode.value.slice( - _inputNode.selectionEnd ? _inputNode.selectionEnd : undefined, - _inputNode.value.length, - ); + _inputNode.value.slice(0, selectionStart) + key + _inputNode.value.slice(selectionEnd); + cursorPosition = selectionStart + key.length; } else { - _inputNode.value += key; + _inputNode.value = + _inputNode.value.slice(0, cursorPosition) + key + _inputNode.value.slice(cursorPosition); + cursorPosition += 1; } mimicKeyPress(_inputNode, key); diff --git a/packages/ui/components/combobox/test/lion-combobox.test.js b/packages/ui/components/combobox/test/lion-combobox.test.js index d83e21d5e..a9967ff0f 100644 --- a/packages/ui/components/combobox/test/lion-combobox.test.js +++ b/packages/ui/components/combobox/test/lion-combobox.test.js @@ -1610,6 +1610,34 @@ describe('lion-combobox', () => { expect(el.checkedIndex).to.equal(0); }); + it('filters options correctly when changing the middle of the word', async () => { + const el = /** @type {LionCombobox} */ ( + await fixture(html` + + Artichoke + Chard + Chicory + Victoria Plum + + `) + ); + + const { _inputNode } = getComboboxMembers(el); + + mimicUserTyping(el, 'char'); + expect(_inputNode.value).to.equal('char'); + await el.updateComplete; // Char + + expect(getFilteredOptionValues(el)).to.eql(['Chard']); + + _inputNode.setSelectionRange(3, 3); + await mimicUserTypingAdvanced(el, ['Backspace', 'i', 'c', 'o']); + await el.updateComplete; // Chicor + + expect(_inputNode.value).to.equal('chicor'); + expect(getFilteredOptionValues(el)).to.eql(['Chicory']); + }); + it('computation of "user intends autofill" works correctly afer autofill', async () => { const el = /** @type {LionCombobox} */ ( await fixture(html`