Skip to content

Commit

Permalink
chore(demo): added new story; rewritten some other stories (#536)
Browse files Browse the repository at this point in the history
For `demo` only:
1. Added PlaygroundLayout component
2. Added `useMarkdownEditorValue()` hook
3. Rewritten `CustomCSSVariables`, `EditorInEditor`, `EscapeConfig`, `Ghost`, `GPT` stories
4. Added new story – `PreserveEmptyRows`
  • Loading branch information
d3m1d0v authored Dec 23, 2024
1 parent a3f8b50 commit c24f2e0
Show file tree
Hide file tree
Showing 14 changed files with 400 additions and 198 deletions.
203 changes: 91 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 Down Expand Up @@ -76,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 @@ -132,7 +124,6 @@ export const Playground = React.memo<PlaygroundProps>((props) => {
markupConfigExtensions,
markupToolbarConfig,
placeholderOptions,
escapeConfig,
enableSubmitInPreview,
hidePreviewAfterSubmit,
needToSetDimensionsForUploadedImages,
Expand Down Expand Up @@ -167,7 +158,6 @@ export const Playground = React.memo<PlaygroundProps>((props) => {
{
preset: 'full',
wysiwygConfig: {
escapeConfig,
placeholderOptions: placeholderOptions,
extensions: (builder) => {
builder
Expand Down Expand Up @@ -304,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;
}
30 changes: 21 additions & 9 deletions demo/stories/css-variables/CSSVariables.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
import React from 'react';

import {PlaygroundMini} from '../../components/PlaygroundMini';
import {toaster} from '@gravity-ui/uikit/toaster-singleton-react-18';

import {MarkdownEditorView, useMarkdownEditor} from '../../../src';
import {PlaygroundLayout} from '../../components/PlaygroundLayout';
import {markup} from '../../defaults/content';

export const CustomCSSVariablesDemo = React.memo((styles) => {
const editor = useMarkdownEditor({initial: {markup}});

return (
<div style={styles}>
<PlaygroundMini
initialEditor="wysiwyg"
settingsVisible
withDefaultInitialContent
stickyToolbar
/>
</div>
<PlaygroundLayout
editor={editor}
style={styles}
view={({className}) => (
<MarkdownEditorView
autofocus
stickyToolbar
settingsVisible
editor={editor}
toaster={toaster}
className={className}
/>
)}
/>
);
});

Expand Down
Loading

0 comments on commit c24f2e0

Please sign in to comment.