Skip to content

Commit

Permalink
Merge branch 'main' into feat/change-default-selection-styles
Browse files Browse the repository at this point in the history
  • Loading branch information
whiteformed authored Dec 24, 2024
2 parents 079dac5 + c24f2e0 commit e96cf53
Show file tree
Hide file tree
Showing 45 changed files with 1,080 additions and 255 deletions.
206 changes: 94 additions & 112 deletions demo/components/Playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {toaster} from '@gravity-ui/uikit/toaster-singleton-react-18';

import {
type DirectiveSyntaxValue,
type EscapeConfig,
type FileUploadHandler,
type MarkdownEditorMode,
MarkdownEditorView,
Expand All @@ -30,21 +29,15 @@ import {YfmHtmlBlock} from '../../src/extensions/additional/YfmHtmlBlock';
import {getSanitizeYfmHtmlBlock} from '../../src/extensions/additional/YfmHtmlBlock/utils';
import type {CodeEditor} from '../../src/markup';
import {ToolbarsPreset} from '../../src/modules/toolbars/types';
import {VERSION} from '../../src/version';
import {getPlugins} from '../defaults/md-plugins';
import useYfmHtmlBlockStyles from '../hooks/useYfmHtmlBlockStyles';
import {block} from '../utils/cn';
import {randomDelay} from '../utils/delay';
import {parseInsertedUrlAsImage} from '../utils/imageUrl';
import {debouncedUpdateLocation as updateLocation} from '../utils/location';

import {WysiwygSelection} from './PMSelection';
import {WysiwygDevTools} from './ProseMirrorDevTools';
import {PlaygroundLayout, b} from './PlaygroundLayout';
import {SplitModePreview} from './SplitModePreview';

import './Playground.scss';

const b = block('playground');
const fileUploadHandler: FileUploadHandler = async (file) => {
console.info('[Playground] Uploading file: ' + file.name);

Check warning on line 42 in demo/components/Playground.tsx

View workflow job for this annotation

GitHub Actions / Verify Files

Unexpected console statement
await randomDelay(1000, 3000);
Expand All @@ -63,6 +56,7 @@ export type PlaygroundProps = {
allowHTML?: boolean;
settingsVisible?: boolean;
initialEditor?: MarkdownEditorMode;
preserveEmptyRows?: boolean;
breaks?: boolean;
linkify?: boolean;
linkifyTlds?: string | string[];
Expand All @@ -75,7 +69,6 @@ export type PlaygroundProps = {
renderPreviewDefined?: boolean;
height?: CSSProperties['height'];
markupConfigExtensions?: Extension[];
escapeConfig?: EscapeConfig;
wysiwygCommandMenuConfig?: wysiwygToolbarConfigs.WToolbarItemData[];
markupToolbarConfig?: ToolbarGroupData<CodeEditor>[];
toolbarsPreset?: ToolbarsPreset;
Expand Down Expand Up @@ -115,6 +108,7 @@ export const Playground = React.memo<PlaygroundProps>((props) => {
allowHTML,
breaks,
linkify,
preserveEmptyRows,
linkifyTlds,
sanitizeHtml,
prepareRawMarkup,
Expand All @@ -130,7 +124,6 @@ export const Playground = React.memo<PlaygroundProps>((props) => {
markupConfigExtensions,
markupToolbarConfig,
placeholderOptions,
escapeConfig,
enableSubmitInPreview,
hidePreviewAfterSubmit,
needToSetDimensionsForUploadedImages,
Expand Down Expand Up @@ -165,7 +158,6 @@ export const Playground = React.memo<PlaygroundProps>((props) => {
{
preset: 'full',
wysiwygConfig: {
escapeConfig,
placeholderOptions: placeholderOptions,
extensions: (builder) => {
builder
Expand Down Expand Up @@ -219,6 +211,7 @@ export const Playground = React.memo<PlaygroundProps>((props) => {
experimental: {
...experimental,
directiveSyntax,
preserveEmptyRows: preserveEmptyRows,
},
prepareRawMarkup: prepareRawMarkup
? (value) => '**prepare raw markup**\n\n' + value
Expand Down Expand Up @@ -301,107 +294,96 @@ export const Playground = React.memo<PlaygroundProps>((props) => {
}, [mdEditor]);

Check warning on line 294 in demo/components/Playground.tsx

View workflow job for this annotation

GitHub Actions / Verify Files

React Hook useEffect has a missing dependency: 'props'. Either include it or remove the dependency array. However, 'props' will change when *any* prop changes, so the preferred fix is to destructure the 'props' object outside of the useEffect call and refer to those specific props inside useEffect

return (
<div className={b()}>
<div className={b('header')}>
Markdown Editor Playground
<span className={b('version')}>{VERSION}</span>
</div>
<div className={b('actions')}>
<DropdownMenu
size="s"
switcher={
<Button size="s" view="flat">
isEmpty: {String(mdEditor.isEmpty())}
</Button>
}
>
<DropdownMenu.Item
text="Clear"
action={() => {
mdEditor.clear();
mdEditor.focus();
}}
/>
<DropdownMenu.Item
text="Append"
action={() => {
mdEditor.append('> append');
mdEditor.focus();
}}
/>
<DropdownMenu.Item
text="Prepend"
action={() => {
mdEditor.prepend('> prepend');
mdEditor.focus();
}}
/>
<DropdownMenu.Item
text="Replace"
action={() => {
mdEditor.replace('> replace');
mdEditor.focus();
}}
/>
<DropdownMenu.Item
text="Move cursor to start"
action={() => {
mdEditor.moveCursor('start');
mdEditor.focus();
}}
/>
<DropdownMenu.Item
text="Move cursor to end"
action={() => {
mdEditor.moveCursor('end');
mdEditor.focus();
}}
/>
<DropdownMenu.Item
text="Move to line"
action={() => {
mdEditor.moveCursor({line: 115});
mdEditor.focus();
}}
/>
</DropdownMenu>
{mdEditor.currentMode === 'markup' && (
<MoveToLine
onClick={(line) => {
if (typeof line !== 'number' || Number.isNaN(line)) return;
mdEditor.moveCursor({line});
mdEditor.focus();
}}
/>
)}
</div>
<hr />
<React.StrictMode>
<div className={b('editor')} style={{height: height ?? 'initial'}}>
<MarkdownEditorView
autofocus
toaster={toaster}
className={b('editor-view')}
stickyToolbar={Boolean(stickyToolbar)}
toolbarsPreset={toolbarsPreset}
wysiwygToolbarConfig={wysiwygToolbarConfig}
markupToolbarConfig={markupToolbarConfig}
settingsVisible={settingsVisible}
editor={mdEditor}
enableSubmitInPreview={enableSubmitInPreview}
hidePreviewAfterSubmit={hidePreviewAfterSubmit}
/>
<WysiwygDevTools editor={mdEditor} />
<WysiwygSelection editor={mdEditor} className={b('pm-selection')} />
</div>
</React.StrictMode>

<hr />

<div className={b('preview')}>
{editorMode === 'wysiwyg' && <pre className={b('markup')}>{mdRaw}</pre>}
</div>
</div>
<PlaygroundLayout
editor={mdEditor}
viewHeight={height}
view={({className}) => (
<MarkdownEditorView
autofocus
toaster={toaster}
className={className}
stickyToolbar={Boolean(stickyToolbar)}
toolbarsPreset={toolbarsPreset}
wysiwygToolbarConfig={wysiwygToolbarConfig}
markupToolbarConfig={markupToolbarConfig}
settingsVisible={settingsVisible}
editor={mdEditor}
enableSubmitInPreview={enableSubmitInPreview}
hidePreviewAfterSubmit={hidePreviewAfterSubmit}
/>
)}
actions={() => (
<>
<DropdownMenu
size="s"
switcher={
<Button size="s" view="flat">
isEmpty: {String(mdEditor.isEmpty())}
</Button>
}
>
<DropdownMenu.Item
text="Clear"
action={() => {
mdEditor.clear();
mdEditor.focus();
}}
/>
<DropdownMenu.Item
text="Append"
action={() => {
mdEditor.append('> append');
mdEditor.focus();
}}
/>
<DropdownMenu.Item
text="Prepend"
action={() => {
mdEditor.prepend('> prepend');
mdEditor.focus();
}}
/>
<DropdownMenu.Item
text="Replace"
action={() => {
mdEditor.replace('> replace');
mdEditor.focus();
}}
/>
<DropdownMenu.Item
text="Move cursor to start"
action={() => {
mdEditor.moveCursor('start');
mdEditor.focus();
}}
/>
<DropdownMenu.Item
text="Move cursor to end"
action={() => {
mdEditor.moveCursor('end');
mdEditor.focus();
}}
/>
<DropdownMenu.Item
text="Move to line"
action={() => {
mdEditor.moveCursor({line: 115});
mdEditor.focus();
}}
/>
</DropdownMenu>
{mdEditor.currentMode === 'markup' && (
<MoveToLine
onClick={(line) => {
if (typeof line !== 'number' || Number.isNaN(line)) return;
mdEditor.moveCursor({line});
mdEditor.focus();
}}
/>
)}
</>
)}
/>
);
});

Expand Down
68 changes: 68 additions & 0 deletions demo/components/PlaygroundLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React, {useEffect} from 'react';

import {useUpdate} from 'react-use';

import type {MarkdownEditorInstance} from '../../src';
import {VERSION} from '../../src/version';
import {useMarkdownEditorValue} from '../hooks/useMarkdownEditorValue';
import {block} from '../utils/cn';

import {WysiwygSelection} from './PMSelection';
import {WysiwygDevTools} from './ProseMirrorDevTools';

import './Playground.scss';

export const b = block('playground');

export type RenderFn = (props: {className?: string}) => React.ReactNode;

export type PlaygroundLayoutProps = {
title?: string;
editor: MarkdownEditorInstance;
view: RenderFn;
viewHeight?: React.CSSProperties['height'];
actions?: RenderFn;
style?: React.CSSProperties;
};

export const PlaygroundLayout: React.FC<PlaygroundLayoutProps> = function PlaygroundLayout(props) {
const {editor} = props;

const forceRender = useUpdate();
const mdMarkup = useMarkdownEditorValue(editor);

useEffect(() => {
editor.on('change-editor-mode', forceRender);
return () => {
editor.off('change-editor-mode', forceRender);
};
}, [editor, forceRender]);

return (
<div className={b()} style={props.style}>
<div className={b('header')}>
{props.title ?? 'Markdown Editor Playground'}
<span className={b('version')}>{VERSION}</span>
</div>

<div className={b('actions')}>{props.actions?.({})}</div>

<hr />

<React.StrictMode>
<div className={b('editor')} style={{height: props.viewHeight ?? 'initial'}}>
{props.view({className: b('editor-view')})}

<WysiwygDevTools editor={editor} />
<WysiwygSelection editor={editor} className={b('pm-selection')} />
</div>
</React.StrictMode>

<hr />

<div className={b('preview')}>
{editor.currentMode === 'wysiwyg' && <pre className={b('markup')}>{mdMarkup}</pre>}
</div>
</div>
);
};
1 change: 0 additions & 1 deletion demo/components/PlaygroundMini.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export type PlaygroundMiniProps = Pick<
| 'initial'
| 'onChangeEditorType'
| 'onChangeSplitModeEnabled'
| 'escapeConfig'
| 'directiveSyntax'
> & {withDefaultInitialContent?: boolean};

Expand Down
1 change: 0 additions & 1 deletion demo/defaults/excluded-controls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ export const excludedControls = [
'withDefaultInitialContent',
'onChangeEditorType',
'onChangeSplitModeEnabled',
'escapeConfig',
];
18 changes: 18 additions & 0 deletions demo/hooks/useMarkdownEditorValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {useEffect, useState} from 'react';

import {type MarkdownEditorInstance, type MarkupString, useDebounce} from '../../src';

export function useMarkdownEditorValue(editor: MarkdownEditorInstance, delay = 500): MarkupString {
const [value, setValue] = useState(() => editor.getValue());

const fn = useDebounce(() => setValue(editor.getValue()), delay);

useEffect(() => {
editor.on('change', fn);
return () => {
editor.off('change', fn);
};
}, [editor, fn]);

return value;
}
Loading

0 comments on commit e96cf53

Please sign in to comment.