From 7a0bdcb7ce69f7d72af4d82345a6ebf8b351558c Mon Sep 17 00:00:00 2001 From: Dmitry Artemov Date: Wed, 21 Aug 2024 11:33:34 +0200 Subject: [PATCH] feat: beforeEditorModeChange (experimental) (#341) --- src/bundle/Editor.ts | 14 +++++++++++++- src/bundle/settings/index.tsx | 18 ++++++++++++++---- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/bundle/Editor.ts b/src/bundle/Editor.ts index 8ed0ebbf..43708f03 100644 --- a/src/bundle/Editor.ts +++ b/src/bundle/Editor.ts @@ -104,7 +104,6 @@ export interface EditorInt type SetEditorModeOptions = Pick; -/** @internal */ type ChangeEditorModeOptions = { mode: EditorMode; reason: 'error-boundary' | 'settings' | 'manually'; @@ -157,6 +156,9 @@ export type EditorOptions = Pick< * You can use it to pre-process the value from the markup editor before it gets into the wysiwyg editor. */ prepareRawMarkup?: (value: MarkupString) => MarkupString; + experimental_beforeEditorModeChange?: ( + options: Pick, + ) => boolean | undefined; splitMode?: SplitMode; renderPreview?: RenderPreview; preset: EditorPreset; @@ -188,6 +190,9 @@ export class EditorImpl extends SafeEventEmitter implements EditorI #fileUploadHandler?: FileUploadHandler; #needToSetDimensionsForUploadedImages: boolean; #prepareRawMarkup?: (value: MarkupString) => MarkupString; + #beforeEditorModeChange?: ( + options: Pick, + ) => boolean | undefined; get _wysiwygView(): PMEditorView { // @ts-expect-error internal typing @@ -349,6 +354,7 @@ export class EditorImpl extends SafeEventEmitter implements EditorI ); this.#prepareRawMarkup = opts.prepareRawMarkup; this.#escapeConfig = opts.escapeConfig; + this.#beforeEditorModeChange = opts.experimental_beforeEditorModeChange; } // ---> implements CodeEditor @@ -385,8 +391,14 @@ export class EditorImpl extends SafeEventEmitter implements EditorI changeEditorMode({emit = true, ...opts}: ChangeEditorModeOptions): void { if (this.#editorMode === opts.mode) return; + + if (this.#beforeEditorModeChange?.({mode: opts.mode, reason: opts.reason}) === false) { + return; + } + this.currentMode = opts.mode; this.emit('rerender', null); + if (emit) { this.emit('change-editor-mode', opts); } diff --git a/src/bundle/settings/index.tsx b/src/bundle/settings/index.tsx index fffeb9d0..3dd7560d 100644 --- a/src/bundle/settings/index.tsx +++ b/src/bundle/settings/index.tsx @@ -32,7 +32,9 @@ const placement: PopupPlacement = ['bottom-end', 'top-end']; const bSettings = cn('editor-settings'); const bContent = cn('settings-content'); -export type EditorSettingsProps = SettingsContentProps & {renderPreviewButton?: boolean}; +export type EditorSettingsProps = Omit & { + renderPreviewButton?: boolean; +}; export const EditorSettings = React.memo(function EditorSettings(props) { const {className, onShowPreviewChange, showPreview, renderPreviewButton} = props; @@ -79,7 +81,7 @@ export const EditorSettings = React.memo(function EditorSet placement={placement} onClose={hidePopup} > - + ); @@ -87,6 +89,7 @@ export const EditorSettings = React.memo(function EditorSet type SettingsContentProps = ClassNameProps & { mode: EditorMode; + onClose: () => void; onModeChange: (mode: EditorMode) => void; onShowPreviewChange: (showPreview: boolean) => void; showPreview: boolean; @@ -101,6 +104,7 @@ const mdHelpPlacement: PopupPlacement = ['bottom', 'bottom-end', 'right-start', const SettingsContent: React.FC = function SettingsContent({ mode, + onClose, onModeChange, toolbarVisibility, onToolbarVisibilityChange, @@ -115,14 +119,20 @@ const SettingsContent: React.FC = function SettingsContent onModeChange('wysiwyg')} + onClick={() => { + onModeChange('wysiwyg'); + onClose(); + }} icon={} > {i18n('settings_wysiwyg')} onModeChange('markup')} + onClick={() => { + onModeChange('markup'); + onClose(); + }} icon={} > {i18n('settings_markup')}