From 9ff9b192467a870c53d05180a652cdadefcb83ad Mon Sep 17 00:00:00 2001 From: Ilya Gorenburg Date: Wed, 17 Jul 2024 10:38:19 -0400 Subject: [PATCH 1/3] fix: prevent inline toolbar from closing in nested instance of editor --- src/components/modules/ui.ts | 6 ++- .../support/utils/nestedEditorInstance.ts | 31 +++++++++++ .../cypress/tests/modules/InlineToolbar.cy.ts | 53 +++++++++++++++++++ 3 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 test/cypress/support/utils/nestedEditorInstance.ts diff --git a/src/components/modules/ui.ts b/src/components/modules/ui.ts index f9c3cbef6..6bbcdb8ce 100644 --- a/src/components/modules/ui.ts +++ b/src/components/modules/ui.ts @@ -847,9 +847,11 @@ export default class UI extends Module { /** * Event can be fired on clicks at non-block-content elements, - * for example, at the Inline Toolbar or some Block Tune element + * for example, at the Inline Toolbar or some Block Tune element. + * We also make sure that the closest block belongs to the current editor and not a parent */ - const clickedOutsideBlockContent = focusedElement.closest(`.${Block.CSS.content}`) === null; + const closestBlock = focusedElement.closest(`.${Block.CSS.content}`); + const clickedOutsideBlockContent = closestBlock === null || (closestBlock.closest(`.${Selection.CSS.editorWrapper}`) !== this.nodes.wrapper); if (clickedOutsideBlockContent) { /** diff --git a/test/cypress/support/utils/nestedEditorInstance.ts b/test/cypress/support/utils/nestedEditorInstance.ts new file mode 100644 index 000000000..4ee608b52 --- /dev/null +++ b/test/cypress/support/utils/nestedEditorInstance.ts @@ -0,0 +1,31 @@ +import { BlockTool, BlockToolConstructorOptions } from '../../../../types'; +import { createEditorWithTextBlocks } from './createEditorWithTextBlocks'; + +export const NESTED_EDITOR_ID = 'nested-editor'; + +/** + * Creates nested Editor instance with paragraph block + */ +export default class NestedEditor implements BlockTool { + private data: { text: string }; + + constructor(value: BlockToolConstructorOptions) { + this.data = value.data; + } + + public render(): HTMLDivElement { + const editorEl = Object.assign(document.createElement('div'), { + id: NESTED_EDITOR_ID, + }); + + editorEl.setAttribute('data-cy', NESTED_EDITOR_ID); + + createEditorWithTextBlocks([ this.data.text ], { holder: NESTED_EDITOR_ID }); + + return editorEl; + } + + public save(): string { + return this.data.text; + } +} diff --git a/test/cypress/tests/modules/InlineToolbar.cy.ts b/test/cypress/tests/modules/InlineToolbar.cy.ts index bc8990bda..ebdb71d67 100644 --- a/test/cypress/tests/modules/InlineToolbar.cy.ts +++ b/test/cypress/tests/modules/InlineToolbar.cy.ts @@ -1,4 +1,5 @@ import Header from '@editorjs/header'; +import NestedEditor, { NESTED_EDITOR_ID } from '../../support/utils/nestedEditorInstance'; describe('Inline Toolbar', () => { it('should appear aligned with left coord of selection rect', () => { @@ -164,4 +165,56 @@ describe('Inline Toolbar', () => { }); }); }); + + describe('Nested Editor instance inline toolbar', () => { + it('should not close inline toolbar of the nested Editor instance when clicking within that toolbar', () => { + cy.createEditor({ + tools: { + nestedEditor: { + class: NestedEditor, + }, + }, + data: { + blocks: [ + { + type: 'paragraph', + data: { + text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + }, + }, + { + type: 'nestedEditor', + data: { + text: 'Nunc pellentesque, tortor nec luctus venenatis', + }, + }, + ], + }, + }); + + cy.get(`[data-cy=${NESTED_EDITOR_ID}]`) + .find('.ce-paragraph') + .selectText('tortor nec luctus'); + + cy.get(`[data-cy=${NESTED_EDITOR_ID}]`) + .find('[data-item-name=link]') + .click(); + + // `wait()` function below is required. without it the test will always pass + // because cypress types the text in the field without delay, while we need some delay (just like user) + // to test the actual case that nested editor inline toolbar is still visible and not closed + + cy.get(`[data-cy=${NESTED_EDITOR_ID}]`) + .find('.ce-inline-tool-input') + .click() + .wait(100) + .type('https://editorjs.io'); + + cy.get(`[data-cy=${NESTED_EDITOR_ID}]`) + .find('.ce-popover__container') + .then(($toolbar) => { + expect($toolbar).to.be.visible; + }); + }); + }); }); From ed60ce3c0d6854eeba8b232f921e025cd82f3258 Mon Sep 17 00:00:00 2001 From: Ilya Gorenburg Date: Wed, 14 Aug 2024 15:20:32 -0400 Subject: [PATCH 2/3] docs: updated changelog.md with fix description --- docs/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index bce98d8e9..88ef3438f 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### 2.30.6 + +- `Fix` - Prevent inline toolbar from closing in nested instance of editor + ### 2.30.5 – `Fix` – Fix exported types From 0a47ab174b68fca187703cd0493a53f75df5468d Mon Sep 17 00:00:00 2001 From: Ilya Gorenburg Date: Wed, 14 Aug 2024 15:36:28 -0400 Subject: [PATCH 3/3] fix: fix import to use `type` --- test/cypress/support/utils/nestedEditorInstance.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cypress/support/utils/nestedEditorInstance.ts b/test/cypress/support/utils/nestedEditorInstance.ts index 4ee608b52..f335cbcee 100644 --- a/test/cypress/support/utils/nestedEditorInstance.ts +++ b/test/cypress/support/utils/nestedEditorInstance.ts @@ -1,4 +1,4 @@ -import { BlockTool, BlockToolConstructorOptions } from '../../../../types'; +import type { BlockTool, BlockToolConstructorOptions } from '../../../../types'; import { createEditorWithTextBlocks } from './createEditorWithTextBlocks'; export const NESTED_EDITOR_ID = 'nested-editor';