Lynx/Modules/Markdown/MarkdownEditor
@sigx/lynx-markdown · Stable · Component library

MarkdownEditor#

True-WYSIWYG markdown editing on the native <sigx-richtext> element. Lightly controlled: markdown in via value, onChange(markdown) out.

Import#

TSX
import { MarkdownEditor } from '@sigx/lynx-markdown/editor';

MarkdownEditor lives on the @sigx/lynx-markdown/editor subpath. Importing the subpath turns the optional peers @sigx/lynx-richtext (the native element) and @sigx/lynx-keyboard into real, required dependencies — install both alongside the package.

Basic usage#

value is initial / lightly-controlled — an incoming value equal to the last emitted markdown is treated as the editor's own echo and ignored, so you can safely feed onChange output back in.

TSX
import { MarkdownEditor } from '@sigx/lynx-markdown/editor';

function Composer() {
  return (
    <MarkdownEditor
      value={'# Draft\n\nStart typing…'}
      placeholder="Write something"
      onChange={(markdown) => saveDraft(markdown)}
    />
  );
}

Toolbar#

Pass toolbar to mount the built-in EditorToolbar, or render your own toolbar standalone against the editor's controller.

TSX
<MarkdownEditor value={draft} onChange={save} toolbar />

Mentions and plugins#

Wire createMentionPlugin (or any MarkdownEditorPlugin) through the editor's plugin surface to add parser syntax, document mapping, serialization, and a trigger that opens a SuggestionPopup session.

TSX
import { MarkdownEditor } from '@sigx/lynx-markdown/editor';
import { createMentionPlugin } from '@sigx/lynx-markdown';

const mention = createMentionPlugin({
  trigger: '@',
  debounce: 150,
  search: async (q) => (await searchDirectory(q)).map((p) => ({ id: p.id, label: p.name })),
});

function Composer() {
  return <MarkdownEditor value={draft} onChange={save} plugins={[mention]} toolbar />;
}

Imperative control#

Grab the editor's MarkdownEditorController via controllerRef to drive formatting, insertion, and fullscreen programmatically.

MethodDescription
toggleBold() / toggleItalic() / toggleStrike() / toggleCode()Toggle inline marks on the selection.
setHeading(level)Set the block heading level (06; 0 clears).
setList(kind)'bullet' | 'ordered' | 'task' | 'none'.
toggleQuote()Toggle a blockquote.
insertLink(href, text?) / insertText(text) / replaceRange(start, end, text)Insert or replace content.
insertChip(chip, replace?)Insert a mention/chip span.
clear()Empty the document.
openFullscreen() / closeFullscreen() / isFullscreen()Fullscreen control — restyles the same element in place, never re-parented.

Native setup & gotchas#

These apply only to the editor subpath — the renderer needs none of them.

  • SafeAreaProvider for the suggestion popup. The popup's keyboard hook reads keyboard height via @sigx/lynx-keyboard's useKeyboard(), which needs a <SafeAreaProvider> ancestor while the fullscreen overlay is open. Without one it reads height 0 (no crash, no warning).
  • ignore-focus keeps the keyboard up. The toolbar, popup, and fullscreen close affordance carry ignore-focus so taps never blur the editor.
  • Fullscreen restyles in place. Going fullscreen re-styles the same mounted element (a fixed inset overlay); it is never re-parented, which would recreate the native view and lose the document.

Props#

PropTypeDescription
valuestringInitial markdown (lightly-controlled; echoes of the last emitted value are ignored).
onChange(markdown: string) => voidFired with serialized markdown as the document changes.
placeholderstringPlaceholder shown while empty.
minLines / maxLinesnumberLine bounds for the native field.
modeMarkdownEditorModeEditor mode.
toolbarbooleanMount the built-in EditorToolbar.
pluginsMarkdownEditorPlugin[]Trigger/inline plugins (e.g. mentions).
controllerRef(c: MarkdownEditorController) => voidReceives the imperative controller.

See the API reference for the full prop list and the editor-subpath exports (mdToDoc, docToMd, plugin contract types).