From 7f72d2817a3db489a763727eef8c476e00749a04 Mon Sep 17 00:00:00 2001 From: Yves Rijckaert Date: Fri, 17 May 2024 14:39:41 +0200 Subject: [PATCH] feat: undo redo rich text tracking [TOL-1987] (#1657) * feat: undo redo rich text tracking * test: tracking undo and redo --- .../rich-text/RichTextEditor.Tracking.spec.ts | 20 +++++++++++++++++ .../src/Toolbar/components/ButtonRedo.tsx | 6 ++++- .../src/Toolbar/components/ButtonUndo.tsx | 6 ++++- .../rich-text/src/internal/types/editor.ts | 8 +++++++ .../plugins/Tracking/createTrackingPlugin.ts | 22 ++++++++++++++++++- 5 files changed, 59 insertions(+), 3 deletions(-) diff --git a/cypress/component/rich-text/RichTextEditor.Tracking.spec.ts b/cypress/component/rich-text/RichTextEditor.Tracking.spec.ts index 859026e2a..5d6074bc3 100644 --- a/cypress/component/rich-text/RichTextEditor.Tracking.spec.ts +++ b/cypress/component/rich-text/RichTextEditor.Tracking.spec.ts @@ -967,4 +967,24 @@ describe('Rich Text Editor - Tracking', { viewportHeight: 2000, viewportWidth: 1 cy.get('@onAction').should('have.callCount', 3); }); }); + + describe('Undo / redo', () => { + it('tracks via toolbar', () => { + richText.editor.click().type('some text.').click(); + richText.toolbar.undo.click(); + cy.get('@onAction').should('be.calledWithExactly', ...action('undo', 'toolbar-icon')); + richText.toolbar.redo.click(); + cy.get('@onAction').should('be.calledWithExactly', ...action('redo', 'toolbar-icon')); + cy.get('@onAction').should('have.callCount', 2); + }); + + it('tracks via shortcut', () => { + richText.editor.click().type('some text.').click(); + richText.editor.click().type(`{${mod}}z`); + cy.get('@onAction').should('be.calledWithExactly', ...action('undo', 'shortcut')); + richText.editor.type(`{${mod}}{shift}z`); + cy.get('@onAction').should('be.calledWithExactly', ...action('redo', 'shortcut')); + cy.get('@onAction').should('have.callCount', 2); + }); + }); }); diff --git a/packages/rich-text/src/Toolbar/components/ButtonRedo.tsx b/packages/rich-text/src/Toolbar/components/ButtonRedo.tsx index 45b2499f0..f81bc2827 100644 --- a/packages/rich-text/src/Toolbar/components/ButtonRedo.tsx +++ b/packages/rich-text/src/Toolbar/components/ButtonRedo.tsx @@ -8,11 +8,15 @@ import { ToolbarButton } from '../../plugins/shared/ToolbarButton'; export const ButtonRedo = () => { const editor = useContentfulEditor(); + const onClickHandler = () => { + editor.redo('toolbar'); + }; + return ( diff --git a/packages/rich-text/src/Toolbar/components/ButtonUndo.tsx b/packages/rich-text/src/Toolbar/components/ButtonUndo.tsx index 350cf7092..b1424c44a 100644 --- a/packages/rich-text/src/Toolbar/components/ButtonUndo.tsx +++ b/packages/rich-text/src/Toolbar/components/ButtonUndo.tsx @@ -8,11 +8,15 @@ import { ToolbarButton } from '../../plugins/shared/ToolbarButton'; export const ButtonUndo = () => { const editor = useContentfulEditor(); + const onClickHandler = () => { + editor.undo('toolbar'); + }; + return ( diff --git a/packages/rich-text/src/internal/types/editor.ts b/packages/rich-text/src/internal/types/editor.ts index 9f7b0e5c9..d721fead5 100644 --- a/packages/rich-text/src/internal/types/editor.ts +++ b/packages/rich-text/src/internal/types/editor.ts @@ -33,6 +33,14 @@ export type Value = Element[]; export type ReactEditor = p.TReactEditor; export interface PlateEditor extends p.PlateEditor { tracking: TrackingPluginActions; + undo: { + (): void; + (source: 'toolbar' | 'shortcut'): void; + }; + redo: { + (): void; + (source: 'toolbar' | 'shortcut'): void; + }; } export type Node = p.ElementOf | p.TextOf; diff --git a/packages/rich-text/src/plugins/Tracking/createTrackingPlugin.ts b/packages/rich-text/src/plugins/Tracking/createTrackingPlugin.ts index 7e835bd22..86c7f9d31 100644 --- a/packages/rich-text/src/plugins/Tracking/createTrackingPlugin.ts +++ b/packages/rich-text/src/plugins/Tracking/createTrackingPlugin.ts @@ -19,6 +19,9 @@ export type RichTextTrackingActionName = // Copy & Paste | 'paste' | 'invalidTablePaste' + // Undo & Redo + | 'undo' + | 'redo' // Hyperlinks | 'cancelCreateHyperlinkDialog' | 'cancelEditHyperlinkDialog' @@ -136,7 +139,7 @@ export const createTrackingPlugin = (onAction: RichTextTrackingActionHandler): P return { key: 'TrackingPlugin', withOverrides: (editor) => { - const { insertData } = editor; + const { insertData, undo, redo } = editor; editor.tracking = trackingActions; @@ -161,6 +164,23 @@ export const createTrackingPlugin = (onAction: RichTextTrackingActionHandler): P insertData(data); }; + editor.undo = (source?: 'toolbar' | 'shortcut') => { + undo(); + if (source === 'toolbar') { + editor.tracking.onToolbarAction('undo'); + } else { + editor.tracking.onShortcutAction('undo'); + } + }; + + editor.redo = (source?: 'toolbar' | 'shortcut') => { + redo(); + if (source === 'toolbar') { + editor.tracking.onToolbarAction('redo'); + } else { + editor.tracking.onShortcutAction('redo'); + } + }; return editor; }, };