From db3749ae150686a33ee1b07ce8b5129535dca292 Mon Sep 17 00:00:00 2001 From: Yuriy Demidov Date: Mon, 3 Jun 2024 18:38:45 +0300 Subject: [PATCH] feat(bundle)!: remove deprecated YfmEditor component (#258) --- demo/PMSelection.tsx | 5 +- demo/Playground.tsx | 210 +++++++------ demo/ProseMirrorDevTools.tsx | 5 +- .../EditorInEditorExtension/index.tsx | 33 +- demo/editor-in-editor/index.tsx | 64 ++-- src/bundle/Editor.ts | 12 +- src/bundle/YfmEditor.tsx | 284 ------------------ src/bundle/YfmEditorView.tsx | 10 +- src/bundle/index.ts | 4 +- 9 files changed, 188 insertions(+), 439 deletions(-) delete mode 100644 src/bundle/YfmEditor.tsx diff --git a/demo/PMSelection.tsx b/demo/PMSelection.tsx index 90699939..e7f2a3a0 100644 --- a/demo/PMSelection.tsx +++ b/demo/PMSelection.tsx @@ -7,16 +7,15 @@ import {type ClassNameProps, isNodeSelection, isTextSelection, isWholeSelection} import type {Editor} from '../src/bundle'; export type WysiwygSelectionProps = ClassNameProps & { - editorRef: React.RefObject; + editor: Editor; }; -export function WysiwygSelection({editorRef, className}: WysiwygSelectionProps) { +export function WysiwygSelection({editor, className}: WysiwygSelectionProps) { const rerender = useUpdate(); useEffectOnce(() => { rerender(); }); - const editor = editorRef.current; const view = editor?.currentType === 'wysiwyg' && editor._wysiwygView; React.useLayoutEffect(() => { diff --git a/demo/Playground.tsx b/demo/Playground.tsx index 2d19cd41..cab4a17c 100644 --- a/demo/Playground.tsx +++ b/demo/Playground.tsx @@ -1,18 +1,17 @@ -import React, {CSSProperties, useCallback} from 'react'; +import React, {CSSProperties, useCallback, useEffect} from 'react'; import {Button, DropdownMenu} from '@gravity-ui/uikit'; import {toaster} from '@gravity-ui/uikit/toaster-singleton-react-18'; import {MarkupString, logger} from '../src'; import { - YfmEditor, - YfmEditorProps, - YfmEditorRef, YfmEditorType, + YfmEditorView, markupToolbarConfigs, + useYfmEditor, wysiwygToolbarConfigs, } from '../src/bundle'; -import {RenderPreview} from '../src/bundle/Editor'; +import {RenderPreview, ToolbarActionData} from '../src/bundle/Editor'; import {Math} from '../src/extensions/yfm/Math'; import {Mermaid} from '../src/extensions/yfm/Mermaid'; import {cloneDeep} from '../src/lodash'; @@ -30,8 +29,10 @@ import {plugins} from './md-plugins'; import './Playground.scss'; const b = block('playground'); -const onAction: YfmEditorProps['onMenuBarAction'] = ({action, editorType}) => { - console.info(`The '${action}' action is performed in the ${editorType}-editor.`); +const fileUploadHandler: FileUploadHandler = async (file) => { + console.info('[Playground] Uploading file: ' + file.name); + await randomDelay(1000, 3000); + return {url: URL.createObjectURL(file)}; }; const mToolbarConfig = [ @@ -91,16 +92,11 @@ export const Playground = React.memo((props) => { } = props; const [editorType, setEditorType] = React.useState(initialEditor ?? 'wysiwyg'); const [mdRaw, setMdRaw] = React.useState(initial || ''); - const editorRef = React.useRef(null); React.useEffect(() => { updateLocation(mdRaw); }, [mdRaw]); - React.useEffect(() => { - console.log('[Playground] MarkdownEditor domElem:', editorRef.current?.domElem()); - }, []); - const renderPreview = useCallback( ({getValue}) => ( ((props) => { [allowHTML, breaks, linkify, linkifyTlds, sanitizeHtml], ); + const mdEditor = useYfmEditor({ + allowHTML, + linkify, + linkifyTlds, + initialMarkup: mdRaw, + breaks: breaks ?? true, + initialEditorType: editorType, + initialSplitModeEnabled: initialSplitModeEnabled, + initialToolbarVisible: true, + splitMode: splitModeOrientation, + renderPreview: renderPreviewDefined ? renderPreview : undefined, + fileUploadHandler, + prepareRawMarkup: prepareRawMarkup + ? (value) => '**prepare raw markup**\n\n' + value + : undefined, + extensionOptions: { + commandMenu: {actions: wCommandMenuConfig}, + }, + extraExtensions: (builder) => + builder + .use(Math, { + loadRuntimeScript: () => { + import( + /* webpackChunkName: "latex-runtime" */ '@diplodoc/latex-extension/runtime' + ); + import( + // @ts-expect-error // no types for styles + /* webpackChunkName: "latex-styles" */ '@diplodoc/latex-extension/runtime/styles' + ); + }, + }) + .use(Mermaid, { + loadRuntimeScript: () => { + import( + /* webpackChunkName: "mermaid-runtime" */ '@diplodoc/mermaid-extension/runtime' + ); + }, + }), + }); + + useEffect(() => { + function onCancel() { + alert('Editor: cancel'); + return true; + } + function onSubmit() { + alert('Editor: submit'); + return true; + } + function onChange() { + setMdRaw(mdEditor.getValue()); + } + function onChangeEditorType({type}: {type: YfmEditorType}) { + setEditorType(type); + } + const onToolbarAction = ({id, editorType: type}: ToolbarActionData) => { + console.info(`The '${id}' action is performed in the ${type}-editor.`); + }; + function onChangeSplitModeEnabled({splitModeEnabled}: {splitModeEnabled: boolean}) { + console.info(`Split mode enabled: ${splitModeEnabled}`); + } + function onChangeToolbarVisibility({visible}: {visible: boolean}) { + console.info('Toolbar visible: ' + visible); + } + + mdEditor.on('cancel', onCancel); + mdEditor.on('submit', onSubmit); + mdEditor.on('change', onChange); + mdEditor.on('toolbar-action', onToolbarAction); + mdEditor.on('change-editor-type', onChangeEditorType); + mdEditor.on('change-split-mode-enabled', onChangeSplitModeEnabled); + mdEditor.on('change-toolbar-visibility', onChangeToolbarVisibility); + + return () => { + mdEditor.off('cancel', onCancel); + mdEditor.off('submit', onSubmit); + mdEditor.off('change', onChange); + mdEditor.off('toolbar-action', onToolbarAction); + mdEditor.off('change-editor-type', onChangeEditorType); + mdEditor.off('change-split-mode-enabled', onChangeSplitModeEnabled); + mdEditor.off('change-toolbar-visibility', onChangeToolbarVisibility); + }; + }, [mdEditor]); + return (
@@ -126,131 +206,75 @@ export const Playground = React.memo((props) => { size="s" switcher={ } > { - editorRef.current?.clear(); - editorRef.current?.focus(); + mdEditor.clear(); + mdEditor.focus(); }} /> { - editorRef.current?.append('> append'); - editorRef.current?.focus(); + mdEditor.append('> append'); + mdEditor.focus(); }} /> { - editorRef.current?.prepend('> prepend'); - editorRef.current?.focus(); + mdEditor.prepend('> prepend'); + mdEditor.focus(); }} /> { - editorRef.current?.replace('> replace'); - editorRef.current?.focus(); + mdEditor.replace('> replace'); + mdEditor.focus(); }} /> { - editorRef.current?.moveCursor('start'); - editorRef.current?.focus(); + mdEditor.moveCursor('start'); + mdEditor.focus(); }} /> { - editorRef.current?.moveCursor('end'); - editorRef.current?.focus(); + mdEditor.moveCursor('end'); + mdEditor.focus(); }} /> { - editorRef.current?.moveCursor({line: 115}); - editorRef.current?.focus(); + mdEditor.moveCursor({line: 115}); + mdEditor.focus(); }} />
- setMdRaw(e.getValue())} - onEditorTypeChange={setEditorType} - onMenuBarAction={onAction} - onFileUpload={fileUploadHandler} + stickyToolbar={Boolean(stickyToolbar)} + wysiwygToolbarConfig={wToolbarConfig} + markupToolbarConfig={mToolbarConfig} settingsVisible={settingsVisible} - onSplitModeEnabledChange={(splitModeEnabled) => { - console.log(`Split mode enabled: ${splitModeEnabled}`); - }} - onMenuVisibleChange={(isMenuVisible) => { - console.log('Menubar visible: ' + isMenuVisible); - }} - prepareRawMarkup={ - prepareRawMarkup - ? (value) => '**prepare raw markup**\n\n' + value - : undefined - } - onCancel={() => { - alert('Editor: cancel'); - return true; - }} - onSubmit={() => { - alert('Editor: submit'); - return true; - }} - extensionOptions={{ - commandMenu: {actions: wCommandMenuConfig}, - }} - wysiwygExtraExtensions={(builder) => - builder - .use(Math, { - loadRuntimeScript: () => { - import( - /* webpackChunkName: "latex-runtime" */ '@diplodoc/latex-extension/runtime' - ); - import( - // @ts-expect-error // no types for styles - /* webpackChunkName: "latex-styles" */ '@diplodoc/latex-extension/runtime/styles' - ); - }, - }) - .use(Mermaid, { - loadRuntimeScript: () => { - import( - /* webpackChunkName: "mermaid-runtime" */ '@diplodoc/mermaid-extension/runtime' - ); - }, - }) - } + editor={mdEditor} /> - - + +
@@ -264,9 +288,3 @@ export const Playground = React.memo((props) => { }); Playground.displayName = 'Playground'; - -const fileUploadHandler: FileUploadHandler = async (file) => { - console.info('[Playground] Uploading file: ' + file.name); - await randomDelay(1000, 3000); - return {url: URL.createObjectURL(file)}; -}; diff --git a/demo/ProseMirrorDevTools.tsx b/demo/ProseMirrorDevTools.tsx index 9c093de0..bc7524c8 100644 --- a/demo/ProseMirrorDevTools.tsx +++ b/demo/ProseMirrorDevTools.tsx @@ -7,16 +7,15 @@ import {useEffectOnce, useUpdate} from 'react-use'; import type {Editor} from '../src/bundle'; export type WysiwygDevToolsProps = { - editorRef: React.RefObject; + editor: Editor; }; -export function WysiwygDevTools({editorRef}: WysiwygDevToolsProps) { +export function WysiwygDevTools({editor}: WysiwygDevToolsProps) { const rerender = useUpdate(); useEffectOnce(() => { rerender(); }); - const editor = editorRef.current; const view = editor?.currentType === 'wysiwyg' && editor._wysiwygView; React.useLayoutEffect(() => { diff --git a/demo/editor-in-editor/EditorInEditorExtension/index.tsx b/demo/editor-in-editor/EditorInEditorExtension/index.tsx index 05b7f1c3..99796bb0 100644 --- a/demo/editor-in-editor/EditorInEditorExtension/index.tsx +++ b/demo/editor-in-editor/EditorInEditorExtension/index.tsx @@ -6,7 +6,7 @@ import {EditorView, NodeView} from 'prosemirror-view'; import {createPortal} from 'react-dom'; import {ExtensionAuto, getReactRendererFromState} from '../../../src'; -import {YfmEditor} from '../../../src/bundle'; +import {YfmEditorView, YfmEditorViewProps, useYfmEditor} from '../../../src/bundle'; import './index.scss'; @@ -91,16 +91,35 @@ class EditorInEditorNodeView implements NodeView { private renderEditor(): React.ReactNode { const {toaster} = this; return createPortal( - , this.dom, ); } } + +type YfmEditorProps = { + initialContent: string; + toaster: YfmEditorViewProps['toaster']; +}; + +function InnerEditor({initialContent, toaster}: YfmEditorProps) { + const mdEditor = useYfmEditor({ + initialMarkup: initialContent, + initialEditorType: 'wysiwyg', + initialToolbarVisible: true, + linkify: true, + breaks: true, + allowHTML: false, + }); + return ( + + ); +} diff --git a/demo/editor-in-editor/index.tsx b/demo/editor-in-editor/index.tsx index 3e8e130f..6cdfeb42 100644 --- a/demo/editor-in-editor/index.tsx +++ b/demo/editor-in-editor/index.tsx @@ -1,9 +1,9 @@ -import React, {useEffect, useRef} from 'react'; +import React, {useEffect} from 'react'; import {toaster} from '@gravity-ui/uikit/toaster-singleton-react-18'; import {BaseNode} from '../../src'; -import {YfmEditor, YfmEditorRef} from '../../src/bundle'; +import {YfmEditorView, useYfmEditor} from '../../src/bundle'; import {VERSION} from '../../src/version'; import {block} from '../cn'; @@ -16,27 +16,31 @@ import { const b = block('playground'); export const PlaygroundEditorInEditor: React.FC = () => { - const editorRef = useRef(null); + const mdEditor = useYfmEditor({ + initialEditorType: 'wysiwyg', + initialToolbarVisible: true, + allowHTML: false, + linkify: true, + breaks: true, + extraExtensions: (builder) => + builder.use(EditorInEditor, { + toaster, + }), + }); useEffect(() => { - if (editorRef.current) { - const view = editorRef.current._wysiwygView; - if (view) { - const {schema} = view.state; - const tr = view.state.tr; - tr.insert(0, [ - schema.node( - BaseNode.Paragraph, - null, - schema.text('This is for development only'), - ), - schema.node(editorInEditorNodeName, { - [EditorInEditorAttr.Markup]: 'Editor-in-Editor content', - }), - schema.node(BaseNode.Paragraph, null, schema.text('After editor')), - ]); - view.dispatch(tr); - } + const view = mdEditor._wysiwygView; + if (view) { + const {schema} = view.state; + const tr = view.state.tr; + tr.insert(0, [ + schema.node(BaseNode.Paragraph, null, schema.text('This is for development only')), + schema.node(editorInEditorNodeName, { + [EditorInEditorAttr.Markup]: 'Editor-in-Editor content', + }), + schema.node(BaseNode.Paragraph, null, schema.text('After editor')), + ]); + view.dispatch(tr); } }, []); @@ -48,22 +52,12 @@ export const PlaygroundEditorInEditor: React.FC = () => {

- - builder.use(EditorInEditor, { - toaster, - }) - } />
diff --git a/src/bundle/Editor.ts b/src/bundle/Editor.ts index c607881c..7fd53946 100644 --- a/src/bundle/Editor.ts +++ b/src/bundle/Editor.ts @@ -23,16 +23,18 @@ export type RenderPreview = ({ mode: 'preview' | 'split'; }) => ReactNode; +export type ToolbarActionData = { + editorType: EditorType; + id: string; + attrs?: {[key: string]: any}; +}; + interface EventMap { change: null; cancel: null; submit: null; - 'toolbar-action': { - editorType: EditorType; - id: string; - attrs?: {[key: string]: any}; - }; + 'toolbar-action': ToolbarActionData; 'change-editor-type': {type: EditorType}; 'change-toolbar-visibility': {visible: boolean}; diff --git a/src/bundle/YfmEditor.tsx b/src/bundle/YfmEditor.tsx deleted file mode 100644 index 8e22bf16..00000000 --- a/src/bundle/YfmEditor.tsx +++ /dev/null @@ -1,284 +0,0 @@ -import React from 'react'; - -import {ClassNameProps} from '../classname'; -import {MarkupString} from '../common'; -import {Extension} from '../core'; - -import type {Editor, RenderPreview, SplitMode, EditorType as YfmEditorType} from './Editor'; -import {YfmEditorView, YfmEditorViewProps} from './YfmEditorView'; -import type {MToolbarData} from './config/markup'; -import type {WToolbarData} from './config/wysiwyg'; -import {UseYfmEditorProps, useYfmEditor} from './useYfmEditor'; - -export type {ExtensionsOptions} from './wysiwyg-preset'; -export type {EditorType as YfmEditorType} from './Editor'; - -/** - * @deprecated - * The `YfmEditor` component will be removed soon. - * Use `useYfmEditor` hook and `YfmEditorView` component instead. - */ -export type YfmEditorRef = Editor & { - domElem: () => HTMLElement | null; -}; - -/** - * @deprecated - * The `YfmEditor` component will be removed soon. - * Use `useYfmEditor` hook and `YfmEditorView` component instead. - */ -export type YfmEditorProps = ClassNameProps & - Pick< - YfmEditorViewProps, - 'settingsVisible' | 'toaster' | 'wysiwygHiddenActionsConfig' | 'markupHiddenActionsConfig' - > & { - /** @default false' - * Split mode orientation - * Has no effect if renderPreview is not defined - */ - splitMode?: SplitMode; - /** @default true - * Is toolbar sticky - */ - stickyToolbar?: boolean; - autofocus?: boolean; - /** initial yfm markup - * Used only on first render - */ - initialContent?: MarkupString; - /** @default 'wysiwyg' - * Used only on first render - */ - initialEditorType?: YfmEditorType; - /** @default true - * Used only on first render - */ - initialMenuVisible?: boolean; - /** @default false - * Used only on first render - */ - initialSplitModeEnabled?: boolean; - - /** menu bar config for markup editor */ - markupMenubarData?: MToolbarData; - /** menu bar config for wysiwyg editor */ - wysiwygMenubarData?: WToolbarData; - /** Used only first value. Сhanging the value will not lead to anything */ - wysiwygExtraExtensions?: Extension; - /** allowing HTML in markup */ - wysiwygAllowHTML?: boolean; - /** markdown-it-attrs options */ - wysiwygAttrs?: UseYfmEditorProps['attrs']; - /** allowing autoconvert URL-like text to links */ - wysiwygLinkify?: boolean; - wysiwygLinkifyTlds?: string | string[]; - /** - * Sets a soft break preferred for breaks inside a paragraph. - * - * If you set the "breaks:true" option for yfm-transform or markdrown-it, - * set this param to "true" too, and the editor will add soft break - * (a break without backslash) for breaks in the paragraph. - * - * Default: "true" – like in yfm-transform - */ - wysiwygBreaks?: boolean; - - /** callback to action in menubar */ - onMenuBarAction?(data: {action: string; editorType: YfmEditorType}): void; - /** callback on change split mode */ - onSplitModeEnabledChange?(splitModeEnabled: boolean): void; - /** function that will transform raw markup to html */ - renderPreview?: RenderPreview; - /** callback on change editor type */ - onEditorTypeChange?(newType: YfmEditorType): void; - /** callback on change menubar visibility */ - onMenuVisibleChange?(visible: boolean): void; - /** callback on editors content change */ - onMarkupChange?(editor: YfmEditorRef, editorType: YfmEditorType): void; - /** - * Called before switching from the markup editor to the wysiwyg editor. - * You can use it to pre-process the value from the markup editor before it gets into the wysiwyg editor. - */ - prepareRawMarkup?(value: string): string; - - /** Submit handler. Return true to stop propagation. */ - onSubmit?(editor: YfmEditorRef): boolean; - /** Cancel handler. Return true to stop propagation. */ - onCancel?(editor: YfmEditorRef): boolean; - - onFileUpload?: UseYfmEditorProps['fileUploadHandler']; - extensionOptions?: UseYfmEditorProps['extensionOptions']; - - /** - * If we need to set dimensions for uploaded images - * - * @default false - */ - needToSetDimensionsForUploadedImages?: boolean; - }; - -/** - * @deprecated - * The `YfmEditor` component will be removed soon. - * Use `useYfmEditor` hook and `YfmEditorView` component instead. - */ -export const YfmEditor = React.forwardRef(function YfmEditor( - { - className, - splitMode, - autofocus, - initialContent, - initialEditorType = 'wysiwyg', - initialMenuVisible: initialToolbarVisible = true, - initialSplitModeEnabled = false, - markupMenubarData: markupToolbarData, - wysiwygMenubarData: wysiwygToolbarData, - wysiwygExtraExtensions, - wysiwygAllowHTML, - wysiwygLinkify, - wysiwygLinkifyTlds, - wysiwygAttrs, - wysiwygBreaks = true, - extensionOptions, - prepareRawMarkup, - onMarkupChange, - onMenuBarAction: onToolbarAction, - onSplitModeEnabledChange, - renderPreview, - onEditorTypeChange, - onMenuVisibleChange: onToolbarVisibleChange, - onCancel, - onSubmit, - onFileUpload, - needToSetDimensionsForUploadedImages, - settingsVisible, - toaster, - wysiwygHiddenActionsConfig, - markupHiddenActionsConfig, - stickyToolbar = true, - }: YfmEditorProps, - ref: React.Ref, -) { - const editor = useYfmEditor({ - splitMode, - renderPreview, - initialMarkup: initialContent, - initialEditorType, - initialToolbarVisible, - initialSplitModeEnabled, - allowHTML: wysiwygAllowHTML, - linkify: wysiwygLinkify, - linkifyTlds: wysiwygLinkifyTlds, - breaks: wysiwygBreaks, - attrs: wysiwygAttrs, - extraExtensions: wysiwygExtraExtensions, - extensionOptions, - prepareRawMarkup, - fileUploadHandler: onFileUpload, - needToSetDimensionsForUploadedImages, - }); - - const viewRef = React.useRef(null); - const self = React.useMemo(() => { - const editorRef = editor as YfmEditorRef; - editorRef.domElem = () => viewRef.current; - return editor as YfmEditorRef; - }, [editor]); - - React.useImperativeHandle(ref, () => self, [self]); - - React.useLayoutEffect(() => { - if (!onSplitModeEnabledChange) return; - const cb = ({splitModeEnabled}: {splitModeEnabled: boolean}) => { - onSplitModeEnabledChange(splitModeEnabled); - }; - self.on('change-split-mode-enabled', cb); - return () => { - self.off('change-split-mode-enabled', cb); - }; - }); - - React.useLayoutEffect(() => { - if (!onEditorTypeChange) return; - const cb = ({type}: {type: YfmEditorType}) => { - onEditorTypeChange(type); - }; - self.on('change-editor-type', cb); - return () => { - self.off('change-editor-type', cb); - }; - }, [onEditorTypeChange, self]); - - React.useLayoutEffect(() => { - if (!onMarkupChange) return; - const cb = () => { - onMarkupChange(self, self.currentType); - }; - self.on('change', cb); - return () => { - self.off('change', cb); - }; - }, [onMarkupChange, self]); - - React.useLayoutEffect(() => { - if (!onCancel) return; - const cb = () => { - onCancel(self); - }; - self.on('cancel', cb); - return () => { - self.off('cancel', cb); - }; - }, [onCancel, self]); - - React.useLayoutEffect(() => { - if (!onSubmit) return; - const cb = () => { - onSubmit(self); - }; - self.on('submit', cb); - return () => { - self.off('submit', cb); - }; - }, [onSubmit, self]); - - React.useLayoutEffect(() => { - if (!onToolbarAction) return; - const cb = ({id, editorType}: {id: string; editorType: YfmEditorType}) => { - onToolbarAction({action: id, editorType}); - }; - self.on('toolbar-action', cb); - return () => { - self.off('toolbar-action', cb); - }; - }, [onToolbarAction, self]); - - React.useLayoutEffect(() => { - if (!onToolbarVisibleChange) return; - const cb = ({visible}: {visible: boolean}) => { - onToolbarVisibleChange(visible); - }; - self.on('change-toolbar-visibility', cb); - return () => { - self.off('change-toolbar-visibility', cb); - }; - }, [onToolbarVisibleChange, self]); - - return ( - - ); -}) as ( - props: YfmEditorProps & {ref?: React.Ref}, -) => JSX.Element; diff --git a/src/bundle/YfmEditorView.tsx b/src/bundle/YfmEditorView.tsx index 7385be49..df5e4985 100644 --- a/src/bundle/YfmEditorView.tsx +++ b/src/bundle/YfmEditorView.tsx @@ -1,8 +1,8 @@ -import React, {useEffect, useMemo, useRef, useState} from 'react'; +import React, {MutableRefObject, useEffect, useMemo, useRef, useState} from 'react'; import type {ToasterPublicMethods} from '@gravity-ui/uikit'; import {ErrorBoundary} from 'react-error-boundary'; -import {useKey, useUpdate} from 'react-use'; +import {useEnsuredForwardedRef, useKey, useUpdate} from 'react-use'; import {ClassNameProps, cn} from '../classname'; import {i18n} from '../i18n/bundle'; @@ -43,6 +43,8 @@ export type YfmEditorViewProps = ClassNameProps & { }; export const YfmEditorView = React.forwardRef((props, ref) => { + const divRef = useEnsuredForwardedRef(ref as MutableRefObject); + const [isMounted, setIsMounted] = useState(false); useEffect(() => { setIsMounted(true); @@ -174,7 +176,7 @@ export const YfmEditorView = React.forwardRef
} + wrapperRef={divRef} /> ) : (
diff --git a/src/bundle/index.ts b/src/bundle/index.ts index b3a1a5f3..9191dfa2 100644 --- a/src/bundle/index.ts +++ b/src/bundle/index.ts @@ -1,5 +1,5 @@ -export * from './YfmEditor'; -export type {Editor, RenderPreview, SplitMode} from './Editor'; +export type {ExtensionsOptions} from './wysiwyg-preset'; +export type {Editor, EditorType as YfmEditorType, RenderPreview, SplitMode} from './Editor'; export * from './context'; export * from './useYfmEditor'; export * from './YfmEditorView';