From 4be9ce5513b47094e9fbedbd7a4772b87889a5c1 Mon Sep 17 00:00:00 2001 From: Daniel Kostro Date: Tue, 12 Sep 2023 16:55:51 +0200 Subject: [PATCH 1/2] UI: fix keydown focusInInput check when input is in a shadow dom --- .../src/modules/preview-web/PreviewWeb.test.ts | 8 ++++++-- .../src/modules/preview-web/PreviewWithSelection.tsx | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/code/lib/preview-api/src/modules/preview-web/PreviewWeb.test.ts b/code/lib/preview-api/src/modules/preview-web/PreviewWeb.test.ts index 41e735ebfddb..c8a6b1a89e64 100644 --- a/code/lib/preview-api/src/modules/preview-web/PreviewWeb.test.ts +++ b/code/lib/preview-api/src/modules/preview-web/PreviewWeb.test.ts @@ -3503,7 +3503,9 @@ describe('PreviewWeb', () => { const preview = await createAndRenderPreview(); preview.onKeydown({ - target: { tagName: 'div', getAttribute: jest.fn().mockReturnValue(null) }, + composedPath: jest + .fn() + .mockReturnValue([{ tagName: 'div', getAttribute: jest.fn().mockReturnValue(null) }]), } as any); expect(mockChannel.emit).toHaveBeenCalledWith(PREVIEW_KEYDOWN, expect.objectContaining({})); @@ -3514,7 +3516,9 @@ describe('PreviewWeb', () => { const preview = await createAndRenderPreview(); preview.onKeydown({ - target: { tagName: 'input', getAttribute: jest.fn().mockReturnValue(null) }, + composedPath: jest + .fn() + .mockReturnValue([{ tagName: 'input', getAttribute: jest.fn().mockReturnValue(null) }]), } as any); expect(mockChannel.emit).not.toHaveBeenCalledWith( diff --git a/code/lib/preview-api/src/modules/preview-web/PreviewWithSelection.tsx b/code/lib/preview-api/src/modules/preview-web/PreviewWithSelection.tsx index ca30544d7c49..b40545bcb4ba 100644 --- a/code/lib/preview-api/src/modules/preview-web/PreviewWithSelection.tsx +++ b/code/lib/preview-api/src/modules/preview-web/PreviewWithSelection.tsx @@ -45,7 +45,7 @@ import type { StorySpecifier } from '../store/StoryIndexStore'; const globalWindow = globalThis; function focusInInput(event: Event) { - const target = event.target as Element; + const target = event.composedPath()[0] as Element; return /input|textarea/i.test(target.tagName) || target.getAttribute('contenteditable') !== null; } From 16968f05a7499083b0de185b2007d9b734479ea6 Mon Sep 17 00:00:00 2001 From: Daniel Kostro Date: Tue, 19 Sep 2023 14:25:32 +0200 Subject: [PATCH 2/2] implement fallback to composedPath in the unlikely case that it doesn't exist or returns an empty array --- .../src/modules/preview-web/PreviewWeb.test.ts | 11 +++++++++++ .../src/modules/preview-web/PreviewWithSelection.tsx | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/code/lib/preview-api/src/modules/preview-web/PreviewWeb.test.ts b/code/lib/preview-api/src/modules/preview-web/PreviewWeb.test.ts index c8a6b1a89e64..8123020b86bb 100644 --- a/code/lib/preview-api/src/modules/preview-web/PreviewWeb.test.ts +++ b/code/lib/preview-api/src/modules/preview-web/PreviewWeb.test.ts @@ -3511,6 +3511,17 @@ describe('PreviewWeb', () => { expect(mockChannel.emit).toHaveBeenCalledWith(PREVIEW_KEYDOWN, expect.objectContaining({})); }); + it('emits PREVIEW_KEYDOWN for regular elements, fallback to event.target', async () => { + document.location.search = '?id=component-one--docs&viewMode=docs'; + const preview = await createAndRenderPreview(); + + preview.onKeydown({ + target: { tagName: 'div', getAttribute: jest.fn().mockReturnValue(null) }, + } as any); + + expect(mockChannel.emit).toHaveBeenCalledWith(PREVIEW_KEYDOWN, expect.objectContaining({})); + }); + it('does not emit PREVIEW_KEYDOWN for input elements', async () => { document.location.search = '?id=component-one--docs&viewMode=docs'; const preview = await createAndRenderPreview(); diff --git a/code/lib/preview-api/src/modules/preview-web/PreviewWithSelection.tsx b/code/lib/preview-api/src/modules/preview-web/PreviewWithSelection.tsx index b40545bcb4ba..73b58cc70ead 100644 --- a/code/lib/preview-api/src/modules/preview-web/PreviewWithSelection.tsx +++ b/code/lib/preview-api/src/modules/preview-web/PreviewWithSelection.tsx @@ -45,7 +45,7 @@ import type { StorySpecifier } from '../store/StoryIndexStore'; const globalWindow = globalThis; function focusInInput(event: Event) { - const target = event.composedPath()[0] as Element; + const target = ((event.composedPath && event.composedPath()[0]) || event.target) as Element; return /input|textarea/i.test(target.tagName) || target.getAttribute('contenteditable') !== null; }