diff --git a/packages/devextreme/js/__internal/ui/__tests__/__mock__/model/html_editor.ts b/packages/devextreme/js/__internal/ui/__tests__/__mock__/model/html_editor.ts index 96f9355e0505..782c55b239a1 100644 --- a/packages/devextreme/js/__internal/ui/__tests__/__mock__/model/html_editor.ts +++ b/packages/devextreme/js/__internal/ui/__tests__/__mock__/model/html_editor.ts @@ -1,3 +1,5 @@ +import HtmlEditor from '@ts/ui/html_editor/html_editor'; + const CLASSES = { content: 'dx-htmleditor-content', toolbarWrapper: 'dx-htmleditor-toolbar-wrapper', @@ -10,6 +12,15 @@ export class HtmlEditorModel { return this.root.querySelector(`.${CLASSES.content}`) as HTMLElement; } + public getInstance(): HtmlEditor { + return HtmlEditor.getInstance(this.root); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public getQuillInstance(): any { + return this.getInstance().getQuillInstance(); + } + public getToolbarWrapper(): HTMLElement { return this.root.querySelector(`.${CLASSES.toolbarWrapper}`) as HTMLElement; } @@ -32,4 +43,11 @@ export class HtmlEditorModel { return event; } + + // Since Jest doesn't have native events, Quill can't process + // click on itself to focus and do all its internal work. + // So we need to set selection manually to simulate focus. + public setQuillFocus(): void { + this.getQuillInstance().setSelection(0, 0); + } } diff --git a/packages/devextreme/js/__internal/ui/html_editor/__tests__/focus_escape.test.ts b/packages/devextreme/js/__internal/ui/html_editor/__tests__/focus_escape.test.ts index ce3db2c637a8..75617adc83c9 100644 --- a/packages/devextreme/js/__internal/ui/html_editor/__tests__/focus_escape.test.ts +++ b/packages/devextreme/js/__internal/ui/html_editor/__tests__/focus_escape.test.ts @@ -100,3 +100,40 @@ describe('HtmlEditor focus escape (Ctrl+Shift+Up/Down)', () => { expect(event.defaultPrevented).toBe(false); }); }); + +describe('HtmlEditor Tab key handling (inlineTabInsertion)', () => { + afterEach(() => { + editors.forEach((instance) => instance.dispose()); + editors.length = 0; + document.body.innerHTML = ''; + }); + + it('should not paste the /t symbol in editor on Tab keypress by default', () => { + const model = createEditor(); + const quill = model.getQuillInstance(); + model.setQuillFocus(); + + expect(quill.getText()).not.toContain('\t'); + + const event = model.pressKeyInContent('Tab'); + + expect(event.defaultPrevented).toBe(false); + expect(quill.getText()).not.toContain('\t'); + }); + + it('should insert a tab character on Tab keypress when inlineTabInsertion is enabled', () => { + const model = createEditor({ + customizeModules: (modules) => { + modules.keyboard.inlineTabInsertion = true; + }, + }); + const quill = model.getQuillInstance(); + model.setQuillFocus(); + + expect(quill.getText()).not.toContain('\t'); + const event = model.pressKeyInContent('Tab'); + + expect(event.defaultPrevented).toBe(true); + expect(quill.getText()).toContain('\t'); + }); +}); diff --git a/packages/devextreme/js/__internal/ui/html_editor/html_editor.ts b/packages/devextreme/js/__internal/ui/html_editor/html_editor.ts index f79315cd5627..88008acdb9f7 100644 --- a/packages/devextreme/js/__internal/ui/html_editor/html_editor.ts +++ b/packages/devextreme/js/__internal/ui/html_editor/html_editor.ts @@ -499,9 +499,10 @@ class HtmlEditor extends Editor { }; } - _getKeyboardModuleConfig(): { onKeydown: (e: DxEvent) => void } { + _getKeyboardModuleConfig(): { onKeydown: (e: DxEvent) => void, inlineTabInsertion: boolean } { return { onKeydown: (e) => this._saveValueChangeEvent(dxEvent(e)), + inlineTabInsertion: false, }; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d31c3c597ef0..cefc347808fb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -92,8 +92,8 @@ catalogs: specifier: 4.4.11 version: 4.4.11 devextreme-quill: - specifier: 1.7.10 - version: 1.7.10 + specifier: 1.8.0 + version: 1.8.0 eslint: specifier: 9.39.4 version: 9.39.4 @@ -447,7 +447,7 @@ importers: version: 4.4.11 devextreme-quill: specifier: 'catalog:' - version: 1.7.10 + version: 1.8.0 devextreme-react: specifier: workspace:* version: link:../../packages/devextreme-react/npm @@ -1222,7 +1222,7 @@ importers: version: link:../../packages/devextreme/artifacts/npm/devextreme-dist devextreme-quill: specifier: 'catalog:' - version: 1.7.10 + version: 1.8.0 devextreme-react: specifier: workspace:~ version: link:../../packages/devextreme-react/npm @@ -1367,7 +1367,7 @@ importers: version: 4.1.69 devextreme-quill: specifier: 'catalog:' - version: 1.7.10 + version: 1.8.0 inferno: specifier: 'catalog:' version: 8.2.3 @@ -9772,8 +9772,8 @@ packages: engines: {node: ^24.16.0} hasBin: true - devextreme-quill@1.7.10: - resolution: {integrity: sha512-AsbMuYAON87Xk77bY4wjjtniONrgQe/WV7LSFxdU58z+bBn0gCkH3hZOJorSwfotThcwRLb150oTJ2ABJcO6DQ==} + devextreme-quill@1.8.0: + resolution: {integrity: sha512-qdSVCjh2d5qEb8nCRzTerjhnfFuzrftnErsgsQzzLbJXaZpQgQfhyH3HC9YpAC3Pgc9HZsI0eEAOlDcGm4YSzw==} devextreme-schematics@1.14.2: resolution: {integrity: sha512-kT2Gf1XpQeG72x4q/SLiFvTrD2wswyrojSkxLWlWwRQZ3kGauFRVg3CPu6s2zZ1eJc705N8W38fwgEgN+nONnA==} @@ -27861,7 +27861,7 @@ snapshots: typescript: 5.9.3 winston: 3.19.0 - devextreme-quill@1.7.10: + devextreme-quill@1.8.0: dependencies: core-js: 3.49.0 eventemitter3: 4.0.7 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index c36e624bfb1a..172bee9fe966 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -9,6 +9,7 @@ preferWorkspacePackages: true saveWorkspaceProtocol: false packageManagerStrict: false engineStrict: true +minimumReleaseAge: 0 overrides: "basic-ftp@<5.3.1": ">=5.3.1" @@ -60,7 +61,7 @@ catalog: devexpress-diagram: 2.2.29 devexpress-gantt: 4.1.69 devextreme-exceljs-fork: 4.4.11 - devextreme-quill: 1.7.10 + devextreme-quill: 1.8.0 "@eslint/js": 9.39.4 eslint: 9.39.4 eslint-config-airbnb-typescript: 18.0.0 @@ -132,23 +133,3 @@ patchedDependencies: testcafe-hammerhead@31.7.8: patches/testcafe-hammerhead@31.7.8.patch systemjs-builder@0.16.15: patches/systemjs-builder@0.16.15.patch babel-core@6.26.3: patches/babel-core@6.26.3.patch - -minimumReleaseAgeExclude: - - "eslint-config-devextreme" - - devextreme-quill@1.7.10 - - '@nx/devkit@23.0.1' - - '@nx/jest@23.0.1' - - '@nx/js@23.0.1' - - '@nx/nx-darwin-arm64@23.0.1' - - '@nx/nx-darwin-x64@23.0.1' - - '@nx/nx-freebsd-x64@23.0.1' - - '@nx/nx-linux-arm-gnueabihf@23.0.1' - - '@nx/nx-linux-arm64-gnu@23.0.1' - - '@nx/nx-linux-arm64-musl@23.0.1' - - '@nx/nx-linux-x64-gnu@23.0.1' - - '@nx/nx-linux-x64-musl@23.0.1' - - '@nx/nx-win32-arm64-msvc@23.0.1' - - '@nx/nx-win32-x64-msvc@23.0.1' - - '@nx/workspace@23.0.1' - - nx@23.0.1 - - devextreme-internal-tools@22.0.0