react-pretext-editor
v0.1.3
Published
A React layout editor and renderer for rich text with free image placement, polygon text wrapping, multi-column layouts, and responsive breakpoints. Built on [@chenglou/pretext](https://github.com/chenglou/pretext) for precise text layout.
Readme
react-pretext-editor
A React layout editor and renderer for rich text with free image placement, polygon text wrapping, multi-column layouts, and responsive breakpoints. Built on @chenglou/pretext for precise text layout.
Features
- Rich markdown editing with bold, italic, links, lists, blockquotes, code blocks
- Free image placement with drag-and-drop positioning
- Polygon text wrapping around custom image shapes
- Multi-column layouts (1-3 columns) with balanced text flow
- Responsive breakpoints with per-breakpoint image positions, columns, and fonts
- Initial/drop caps with custom decorative fonts
- Font selection with configurable font options and sizes
- Live preview toggle within the editor
- Keyboard shortcuts for markdown (Cmd+B/I/K, wrap selection, smart lists)
Installation
npm install react-pretext-editorUsage
Editor
import { Editor, parseMarkdown } from 'react-pretext-editor'
import type { LayoutData, FontOption } from 'react-pretext-editor'
const fonts: FontOption[] = [
{ name: 'Lato', bodyFont: '16px Lato, sans-serif' },
{ name: 'Georgia', bodyFont: '16px Georgia, serif' },
]
function App() {
const [blocks, setBlocks] = useState(() => parseMarkdown('# Hello\n\nWorld'))
const [layout, setLayout] = useState<LayoutData>({ images: [] })
return (
<Editor
blocks={blocks}
layout={layout}
onLayoutChange={setLayout}
onBlocksChange={setBlocks}
availableFonts={fonts}
width={1000}
expandable
/>
)
}Renderer (display only)
import { Renderer } from 'react-pretext-editor'
function BlogPost({ blocks, layout }) {
return (
<Renderer
blocks={blocks}
layout={layout}
availableFonts={fonts}
/>
)
}Editor Props
| Prop | Type | Description |
|------|------|-------------|
| blocks | Block[] | Content blocks (from parseMarkdown) |
| layout | LayoutData | Layout state (images, columns, fonts, breakpoints) |
| onLayoutChange | (layout) => void | Called when layout changes |
| onBlocksChange | (blocks) => void | Called when text content changes |
| availableFonts | FontOption[] | Font choices for the font selector |
| availableInitialFonts | InitialCapOption[] | Fonts for drop caps |
| config | LayoutConfig | Default layout config overrides |
| resolveImageUrl | (url, filename) => string | Custom image URL resolver |
| width | number \| string | Editor width |
| height | number \| string | Minimum editor height |
| expandable | boolean | Expand width when multiple panels are active |
Data Model
Block
interface Block {
type: 'heading' | 'paragraph' | 'list' | 'blockquote' | 'code' | 'hr'
text: string
segments?: TextSegment[] // Inline formatting
tag?: string // h1/h2/h3, ul/ol
items?: Block[] // List items
language?: string // Code block language
}LayoutData
interface LayoutData {
images: LayoutImage[]
columns?: number // 1-3
editorWidth?: number
fontFamily?: string
fontSize?: number
initialCap?: boolean
initialCapFont?: string
initialCapSize?: number
initialCapOffsetX?: number
initialCapOffsetY?: number
breakpoints?: LayoutBreakpoint[]
}LayoutImage
interface LayoutImage {
filename: string
alt: string
url: string
aspectRatio: number
x: number // Absolute x position
y: number // Absolute y position
width: number
polygon?: PolygonPoint[] // Custom text wrapping shape
}Keyboard Shortcuts (Write mode)
| Shortcut | Action |
|----------|--------|
| Cmd+B | Bold |
| Cmd+I | Italic |
| Cmd+K | Insert link |
| Tab | Indent list item |
| Shift+Tab | Unindent list item |
| Enter in list | Continue list / break out if empty |
| Select + * | Wrap selection with *...* |
| Select + ` | Wrap selection with backticks |
License
MIT
