Skip to content

feat(API): add setPreviewVisible and changeSplitModeEnabled in API#1153

Open
ReFFaT wants to merge 1 commit into
mainfrom
feat-API-add-methods
Open

feat(API): add setPreviewVisible and changeSplitModeEnabled in API#1153
ReFFaT wants to merge 1 commit into
mainfrom
feat-API-add-methods

Conversation

@ReFFaT

@ReFFaT ReFFaT commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Moves markup preview state out of React component into EditorImpl and exposes programmatic control via the public MarkdownEditorInstance interface.

What's new
previewVisible: boolean — read current preview state
setPreviewVisible(visible?: boolean) — show/hide/toggle full-screen preview; auto-disables split mode
splitModeEnabled: boolean — read current split-mode state
changeSplitModeEnabled(opts) — moved to public interface; auto-hides preview when enabled
change-preview-visible event — emitted on every visibility change
Internal
Removed useBooleanState for showPreview from MarkdownEditorView; state is now owned by EditorImpl
Added unit tests for both methods covering toggle, mutual exclusion, and no-op behaviour
Demo
Added "Toggle Preview" and "Toggle Split Mode" buttons to Playground (markup mode only).

Summary by Sourcery

Expose programmatic control of full-screen markup preview and split mode via the Markdown editor API and centralize preview state in the core editor implementation.

New Features:

  • Add previewVisible and splitModeEnabled read-only flags to the public MarkdownEditorInstance API.
  • Add setPreviewVisible API to control or toggle full-screen markup preview, automatically coordinating with split mode.
  • Expose changeSplitModeEnabled on the public MarkdownEditorInstance and emit a change-preview-visible event on preview visibility changes.
  • Extend the demo Playground with controls to toggle preview and split mode via the new APIs.

Enhancements:

  • Move preview visibility state from the React MarkdownEditorView component into EditorImpl as the single source of truth.

Tests:

  • Add unit tests for EditorImpl covering setPreviewVisible, changeSplitModeEnabled, their interaction, and no-op behavior when state does not change.

@sourcery-ai

sourcery-ai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds programmatic control over markup preview and split mode to the public Markdown editor API, moves preview visibility state into EditorImpl, introduces a change-preview-visible event, and wires the new behaviour into the React view, tests, and demo playground.

File-Level Changes

Change Details Files
Move preview visibility state from React view into EditorImpl and wire view to the new API.
  • Removed local showPreview/useBooleanState from MarkdownEditorView and EditorWrapper props.
  • Derived showPreview from editor.previewVisible and updated callbacks to use editor.setPreviewVisible.
  • Ensured mode changes and split-mode changes clear preview via editor.setPreviewVisible(false).
  • Updated keyboard handlers (preview toggle and submit) to call editor.setPreviewVisible with appropriate arguments and dependencies.
packages/editor/src/bundle/MarkdownEditorView.tsx
Expose preview visibility and split mode control via the core EditorImpl and public MarkdownEditorInstance API, including a new change-preview-visible event.
  • Extended EditorInt and EditorImpl with previewVisible getter and setPreviewVisible method, initializing previewVisible and keeping it mutually exclusive with splitModeEnabled.
  • Updated changeSplitModeEnabled to auto-hide preview when enabling split mode, emitting change-preview-visible and rerender events as needed.
  • Extended MarkdownEditorInstance public type with splitModeEnabled, previewVisible, changeSplitModeEnabled, and setPreviewVisible.
  • Added change-preview-visible to the EventMap so consumers can subscribe to preview visibility changes.
packages/editor/src/bundle/Editor.ts
packages/editor/src/bundle/editor-public-types.ts
packages/editor/src/bundle/events.ts
Add unit tests for preview/split-mode behaviour in EditorImpl.
  • Created EditorImpl tests covering setPreviewVisible behaviour (explicit set and toggle).
  • Added tests for changeSplitModeEnabled, including interaction with preview visibility.
  • Verified mutual exclusion between preview and split mode and that no-op calls do not emit events.
packages/editor/src/bundle/Editor.test.ts
Update Playground demo to showcase and track the new preview and split mode API.
  • Track previewVisible and splitModeEnabled in Playground component state based on editor events, including new change-preview-visible.
  • Subscribed/unsubscribed to change-preview-visible in the demo lifecycle.
  • Added DropdownMenu items to toggle preview and split mode via mdEditor.setPreviewVisible() and mdEditor.changeSplitModeEnabled().
demo/src/components/Playground.tsx

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • In MarkdownEditorView, the useEffect that focuses divRef depends on editor.previewVisible, which is a property read off the instance; this will both upset exhaustive-deps linters and can be misleading for readers—consider deriving showPreview once (as you already do) and using that in the dependency array instead of accessing editor.previewVisible directly.
  • In EditorWrapper’s useKey for submit, the dependency array still includes showPreview even though the callback no longer references it; trimming unused dependencies here (and in other hooks where the deps no longer match the callback body after this refactor) will make the hooks’ behavior and intent clearer.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `MarkdownEditorView`, the `useEffect` that focuses `divRef` depends on `editor.previewVisible`, which is a property read off the instance; this will both upset exhaustive-deps linters and can be misleading for readers—consider deriving `showPreview` once (as you already do) and using that in the dependency array instead of accessing `editor.previewVisible` directly.
- In `EditorWrapper`’s `useKey` for submit, the dependency array still includes `showPreview` even though the callback no longer references it; trimming unused dependencies here (and in other hooks where the deps no longer match the callback body after this refactor) will make the hooks’ behavior and intent clearer.

## Individual Comments

### Comment 1
<location path="demo/src/components/Playground.tsx" line_range="157" />
<code_context>
         yfmMods,
     } = props;
     const [editorMode, setEditorMode] = useState<MarkdownEditorMode>(initialEditor ?? 'wysiwyg');
+    const [previewVisible, setPreviewVisible] = useState(false);
+    const [splitModeEnabled, setSplitModeEnabled] = useState(false);
     const [mdRaw, setMdRaw] = useState<MarkupString>(initial || '');
</code_context>
<issue_to_address>
**issue (complexity):** Consider removing the duplicated React state for preview and split mode and rely on mdEditor as the single source of truth for these flags.

You can drop the mirrored React state and derive everything directly from `mdEditor`, keeping logging while reducing complexity and desync risk.

### 1. Remove duplicated React state

```ts
// remove these
- const [previewVisible, setPreviewVisible] = useState(false);
- const [splitModeEnabled, setSplitModeEnabled] = useState(false);
```

### 2. Keep listeners for logging only

```ts
function onChangeSplitModeEnabled({splitModeEnabled}: {splitModeEnabled: boolean}) {
    props.onChangeSplitModeEnabled?.(splitModeEnabled);
    console.info(`Split mode enabled: ${splitModeEnabled}`);
}

function onChangePreviewVisible({visible}: {visible: boolean}) {
    console.info(`Preview visible: ${visible}`);
}
```

No need to update React state here; `mdEditor` is the single source of truth.

### 3. Read state from `mdEditor` in the dropdown

Use `mdEditor.previewVisible` / `mdEditor.splitModeEnabled` for labels and toggling:

```tsx
{editorMode === 'markup' && (
    <DropdownMenu.Item
        text={`Toggle Preview (${mdEditor.previewVisible ? 'on' : 'off'})`}
        action={() => {
            mdEditor.setPreviewVisible({
                visible: !mdEditor.previewVisible,
            });
        }}
    />
)}

{editorMode === 'markup' && (
    <DropdownMenu.Item
        text={`Toggle Split Mode (${mdEditor.splitModeEnabled ? 'on' : 'off'})`}
        action={() => {
            mdEditor.changeSplitModeEnabled({
                splitModeEnabled: !mdEditor.splitModeEnabled,
            });
        }}
    />
)}
```

This keeps the behavior (including logging and the dropdown labels) while:

- Eliminating duplicated local state.
- Avoiding sync handlers whose only job was to mirror editor state into React.
- Ensuring there’s a single source of truth (`EditorImpl`) for these flags.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

yfmMods,
} = props;
const [editorMode, setEditorMode] = useState<MarkdownEditorMode>(initialEditor ?? 'wysiwyg');
const [previewVisible, setPreviewVisible] = useState(false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider removing the duplicated React state for preview and split mode and rely on mdEditor as the single source of truth for these flags.

You can drop the mirrored React state and derive everything directly from mdEditor, keeping logging while reducing complexity and desync risk.

1. Remove duplicated React state

// remove these
- const [previewVisible, setPreviewVisible] = useState(false);
- const [splitModeEnabled, setSplitModeEnabled] = useState(false);

2. Keep listeners for logging only

function onChangeSplitModeEnabled({splitModeEnabled}: {splitModeEnabled: boolean}) {
    props.onChangeSplitModeEnabled?.(splitModeEnabled);
    console.info(`Split mode enabled: ${splitModeEnabled}`);
}

function onChangePreviewVisible({visible}: {visible: boolean}) {
    console.info(`Preview visible: ${visible}`);
}

No need to update React state here; mdEditor is the single source of truth.

3. Read state from mdEditor in the dropdown

Use mdEditor.previewVisible / mdEditor.splitModeEnabled for labels and toggling:

{editorMode === 'markup' && (
    <DropdownMenu.Item
        text={`Toggle Preview (${mdEditor.previewVisible ? 'on' : 'off'})`}
        action={() => {
            mdEditor.setPreviewVisible({
                visible: !mdEditor.previewVisible,
            });
        }}
    />
)}

{editorMode === 'markup' && (
    <DropdownMenu.Item
        text={`Toggle Split Mode (${mdEditor.splitModeEnabled ? 'on' : 'off'})`}
        action={() => {
            mdEditor.changeSplitModeEnabled({
                splitModeEnabled: !mdEditor.splitModeEnabled,
            });
        }}
    />
)}

This keeps the behavior (including logging and the dropdown labels) while:

  • Eliminating duplicated local state.
  • Avoiding sync handlers whose only job was to mirror editor state into React.
  • Ensuring there’s a single source of truth (EditorImpl) for these flags.

@gravity-ui

gravity-ui Bot commented Jun 21, 2026

Copy link
Copy Markdown

Storybook Deployed

@gravity-ui

gravity-ui Bot commented Jun 21, 2026

Copy link
Copy Markdown

🎭 Playwright Report

@ReFFaT ReFFaT force-pushed the feat-API-add-methods branch from e707ef6 to 4534bb5 Compare June 24, 2026 00:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant