From 109a309459bf8abae4818d834a566e4b9117acdf Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Thu, 22 Feb 2024 10:09:41 -0500 Subject: [PATCH 1/3] fix: opening drop should focus on next available option only initially - opening the drop should move highlight to next available option but only on the initial opening, meaning that if we close and reopen the drop then it should keep its highlight index. Prior to this PR, closing/reopening multiple times was moving the highlight down by 1 option every time which is wrong --- .../src/MultipleSelectInstance.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/multiple-select-vanilla/src/MultipleSelectInstance.ts b/packages/multiple-select-vanilla/src/MultipleSelectInstance.ts index 9ef4f7af..e7c72218 100644 --- a/packages/multiple-select-vanilla/src/MultipleSelectInstance.ts +++ b/packages/multiple-select-vanilla/src/MultipleSelectInstance.ts @@ -1096,7 +1096,14 @@ export class MultipleSelectInstance { ulElm.focus(); } } - this.moveFocusDown(); + + if (this._currentHighlightIndex < 0) { + // on open drop initial, we'll focus on next available option + this.moveFocusDown(); + } else { + // if it was already opened earlier, we'll keep same option index focused + this.highlightCurrentOption(); + } if (this.options.autoAdjustDropWidthByTextSize) { this.adjustDropWidthByText(); From 0aac64b68f7ca114c6f89c0f73553e970a8b627f Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Thu, 22 Feb 2024 10:16:13 -0500 Subject: [PATCH 2/3] chore: format entire file on save to fix formatting issue --- .vscode/settings.json | 3 ++- packages/multiple-select-vanilla/src/MultipleSelectInstance.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 67a46574..4c204cf2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,7 @@ { "editor.defaultFormatter": "biomejs.biome", "editor.formatOnSave": true, + "editor.formatOnSaveMode": "file", "editor.formatOnPaste": false, "typescript.tsdk": "node_modules\\typescript\\lib" -} \ No newline at end of file +} diff --git a/packages/multiple-select-vanilla/src/MultipleSelectInstance.ts b/packages/multiple-select-vanilla/src/MultipleSelectInstance.ts index e7c72218..4a721de6 100644 --- a/packages/multiple-select-vanilla/src/MultipleSelectInstance.ts +++ b/packages/multiple-select-vanilla/src/MultipleSelectInstance.ts @@ -1096,7 +1096,7 @@ export class MultipleSelectInstance { ulElm.focus(); } } - + if (this._currentHighlightIndex < 0) { // on open drop initial, we'll focus on next available option this.moveFocusDown(); From 9bd22cba5b998db81011f351e7fd3f4a92fdccdb Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Thu, 22 Feb 2024 11:10:06 -0500 Subject: [PATCH 3/3] chore: move highlight back to top after clearing filter --- .../src/MultipleSelectInstance.ts | 11 +++++++---- playwright/e2e/options35.spec.ts | 18 +++++++----------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/multiple-select-vanilla/src/MultipleSelectInstance.ts b/packages/multiple-select-vanilla/src/MultipleSelectInstance.ts index 4a721de6..217ac17d 100644 --- a/packages/multiple-select-vanilla/src/MultipleSelectInstance.ts +++ b/packages/multiple-select-vanilla/src/MultipleSelectInstance.ts @@ -29,7 +29,7 @@ export class MultipleSelectInstance { protected fromHtml = false; protected choiceElm!: HTMLButtonElement; protected closeElm?: HTMLElement | null; - protected closeSearchElm?: HTMLElement | null; + protected clearSearchIconElm?: HTMLElement | null; protected filterText = ''; protected updateData: any[] = []; protected data?: Array = []; @@ -718,7 +718,7 @@ export class MultipleSelectInstance { 'option-list-scroll', ]); - this.closeSearchElm = this.filterParentElm?.querySelector('.icon-close'); + this.clearSearchIconElm = this.filterParentElm?.querySelector('.icon-close'); this.searchInputElm = this.dropElm.querySelector('.ms-search input'); this.selectAllElm = this.dropElm.querySelector(`input[data-name="${this.selectAllName}"]`); this.selectGroupElms = this.dropElm.querySelectorAll( @@ -774,13 +774,16 @@ export class MultipleSelectInstance { }) as EventListener); } - if (this.closeSearchElm) { - this._bindEventService.bind(this.closeSearchElm, 'click', ((e: MouseEvent) => { + if (this.clearSearchIconElm) { + this._bindEventService.bind(this.clearSearchIconElm, 'click', ((e: MouseEvent) => { e.preventDefault(); if (this.searchInputElm) { this.searchInputElm.value = ''; this.searchInputElm.focus(); } + // move highlight back to top of the list + this._currentHighlightIndex = -1; + this.moveFocusDown(); this.filter(); }) as EventListener); } diff --git a/playwright/e2e/options35.spec.ts b/playwright/e2e/options35.spec.ts index 060f800d..48d5be60 100644 --- a/playwright/e2e/options35.spec.ts +++ b/playwright/e2e/options35.spec.ts @@ -26,14 +26,12 @@ test.describe('Options 35 - Diacritic Parser', () => { await page.locator('[data-test=select1] .ms-search .icon-close').click(); await expect(page.locator('[data-test=select1] .ms-search span')).toHaveText(''); - await page.getByRole('textbox', { name: '🔎︎' }).fill('û'); - await page.keyboard.press('Enter'); + await page.getByRole('textbox', { name: '🔎︎' }).pressSequentially('û '); await expect(page.locator('input.in-log')).toHaveValue('û'); await expect(page.locator('input.out-log')).toHaveValue('u'); await expect(page.locator('[data-test=select1].ms-drop li:not(.ms-no-results)')).toHaveCount(3); await page.locator('[data-test=select1] .ms-search .icon-close').click(); await page.getByRole('textbox', { name: '🔎︎' }).fill('u'); - await page.keyboard.press('Enter'); await page.locator('[data-test=select1] span').filter({ hasText: 'Juin' }).click(); await page.locator('[data-test=select1] span').filter({ hasText: 'Juillet' }); await page.locator('[data-test=select1] span').filter({ hasText: 'Août' }).click(); @@ -41,8 +39,8 @@ test.describe('Options 35 - Diacritic Parser', () => { await expect(parentSpan).toHaveText('Février, Juin, Août'); await page.locator('[data-test=select1].ms-parent').click(); - // // 2nd Select - // // -------------- + // 2nd Select + // -------------- await page.locator('[data-test=select2].ms-parent').click(); await page.getByRole('textbox', { name: '🔎︎' }).pressSequentially('év'); await page.locator('[data-test=select2] span').filter({ hasText: 'Février' }).click(); @@ -56,22 +54,20 @@ test.describe('Options 35 - Diacritic Parser', () => { await expect(page.locator('[data-test=select2] .ms-search span')).toHaveText(''); await expect(page.locator('[data-test=select2].ms-drop li:not(.ms-no-results)')).toHaveCount(12); - await page.getByRole('textbox', { name: '🔎︎' }).fill('e'); - await page.keyboard.press('Enter'); + await page.getByRole('textbox', { name: '🔎︎' }).press('e'); await expect(page.locator('[data-test=select2].ms-drop li:not(.ms-no-results)')).toHaveCount(7); await page.locator('[data-test=select2] .ms-search .icon-close').click(); await expect(page.locator('[data-test=select2] .ms-search span')).toHaveText(''); - await page.getByRole('textbox', { name: '🔎︎' }).fill('û'); - await page.keyboard.press('Enter'); + await page.getByRole('textbox', { name: '🔎︎' }).pressSequentially('û '); await expect(page.locator('[data-test=select2].ms-drop li:not(.ms-no-results)')).toHaveCount(3); await page.locator('[data-test=select2] .ms-search .icon-close').click(); - await page.getByRole('textbox', { name: '🔎︎' }).pressSequentially('u'); + await page.getByRole('textbox', { name: '🔎︎' }).press('u'); await page.locator('[data-test=select2] span').filter({ hasText: 'Juin' }).click(); await page.locator('[data-test=select2] span').filter({ hasText: 'Juillet' }); await page.locator('[data-test=select2] span').filter({ hasText: 'Août' }).click(); const parentSpan2 = await page.locator('div[data-test=select2] .ms-choice span'); - await expect(parentSpan2).toHaveText('Juin, Août'); + await expect(parentSpan2).toHaveText('Février, Juin, Août'); await page.locator('[data-test=select2].ms-parent').click(); }); });