diff --git a/packages/combobox/README.md b/packages/combobox/README.md index 56736707f..1094a3b3c 100644 --- a/packages/combobox/README.md +++ b/packages/combobox/README.md @@ -267,7 +267,7 @@ export const invokerButton = () => html` Validation can be used as normal, below is an example of a combobox with a `Required` validator. -```js story +```js preview-story export const validation = () => { loadDefaultFeedbackMessages(); Required.getMessage = () => 'Please enter a value'; @@ -278,7 +278,6 @@ export const validation = () => { .validators="${[new Required()]}" name="favoriteMovie" label="Favorite movie" - autocomplete="both" > Rocky Rocky II diff --git a/packages/combobox/src/LionCombobox.js b/packages/combobox/src/LionCombobox.js index dfb7f18b4..a08cc6bdc 100644 --- a/packages/combobox/src/LionCombobox.js +++ b/packages/combobox/src/LionCombobox.js @@ -433,8 +433,8 @@ export class LionCombobox extends OverlayMixin(LionListbox) { * * @param {EventTarget & import('../types/choice-group/ChoiceInputMixinTypes').ChoiceInputHost} target */ - _repropagationConditionFails(target) { - return super._repropagationConditionFails(target) && this.formElements?.some(el => el.checked); + _repropagationCondition(target) { + return super._repropagationCondition(target) || this.formElements.every(el => !el.checked); } /* eslint-disable no-param-reassign */ @@ -482,6 +482,7 @@ export class LionCombobox extends OverlayMixin(LionListbox) { prevValue.length && curValue.length && prevValue[0].toLowerCase() !== curValue[0].toLowerCase(); + return userIsAddingChars || userStartsNewWord; } diff --git a/packages/combobox/test/lion-combobox.test.js b/packages/combobox/test/lion-combobox.test.js index c9b8756f9..2df02778f 100644 --- a/packages/combobox/test/lion-combobox.test.js +++ b/packages/combobox/test/lion-combobox.test.js @@ -450,22 +450,23 @@ describe('lion-combobox', () => { it('works with validation', async () => { const el = /** @type {LionCombobox} */ (await fixture(html` - Artichoke + Artichoke Chard Chicory Victoria Plum `)); - - // open - el._comboboxNode.dispatchEvent(new Event('focusin', { bubbles: true, composed: true })); - - mimicUserTyping(el, 'art'); - await el.updateComplete; expect(el.checkedIndex).to.equal(0); - mimicUserTyping(el, ''); + // Simulate backspace deleting the char at the end of the string + el._inputNode.dispatchEvent(new KeyboardEvent('keydown', { key: 'Backspace' })); + el._inputNode.dispatchEvent(new Event('input')); + const arr = el._inputNode.value.split(''); + arr.splice(el._inputNode.value.length - 1, 1); + el._inputNode.value = arr.join(''); await el.updateComplete; + el.dispatchEvent(new Event('blur')); + expect(el.checkedIndex).to.equal(-1); await el.feedbackComplete; expect(el.hasFeedbackFor).to.include('error'); diff --git a/packages/form-core/src/FocusMixin.js b/packages/form-core/src/FocusMixin.js index f9871ddca..cc016f947 100644 --- a/packages/form-core/src/FocusMixin.js +++ b/packages/form-core/src/FocusMixin.js @@ -6,6 +6,7 @@ import { FormControlMixin } from './FormControlMixin.js'; * @param {import('@open-wc/dedupe-mixin').Constructor} superclass */ const FocusMixinImplementation = superclass => + // @ts-expect-error false positive for incompatible static get properties. Lit-element merges super properties already for you. // eslint-disable-next-line no-unused-vars, max-len, no-shadow class FocusMixin extends FormControlMixin(superclass) { static get properties() { diff --git a/packages/form-core/src/FormControlMixin.js b/packages/form-core/src/FormControlMixin.js index 68e7af09d..e3504c5e5 100644 --- a/packages/form-core/src/FormControlMixin.js +++ b/packages/form-core/src/FormControlMixin.js @@ -801,7 +801,7 @@ const FormControlMixinImplementation = superclass => // We only send the checked changed up (not the unchecked). In this way a choice group // (radio-group, checkbox-group, select/listbox) acts as an 'endpoint' (a single Field) // just like the native