Rich Content
Imports
import {
DefaultContentEditableAdapter,
RichContentService,
type RichContentConfig,
} from '@codella-software/utils/rich-content'
import {
RichContentProvider,
useRichContent,
useRichContentContext,
} from '@codella-software/react'
Core service
const service = RichContentService.create({
enableHistory: true,
maxHistorySteps: 100,
placeholder: 'Write something…',
})
service.insertText('Hello')
service.toggleMark('bold')
service.insertHeading(2)
service.insertList('unordered')
service.undo()
Public methods include:
getContent$()getState$()getCanUndo$()getCanRedo$()getIsFocused$()getMentions$()getSelectedFormats$()getContent()getState()getPlainText()attachAdapter(adapter)detachAdapter()getAdapter()insertText(text, marks?)insertParagraph()insertHeading(level)insertImage(url, attrs?)uploadImage(file)insertMention(id, label, meta?)insertList(listType)toggleMark(mark)deleteContent()setFocus(focused)setSelection(selection)undo()redo()clearHistory()
React hook
function Editor() {
const editorRef = useRef<HTMLDivElement>(null)
const {
content,
isFocused,
canUndo,
canRedo,
selectedFormats,
toggleMark,
insertHeading,
undo,
redo,
setFocus,
} = useRichContent({
editorRef,
placeholder: 'Write something…',
})
return (
<>
<button onClick={() => toggleMark('bold')}>
{selectedFormats.has('bold') ? 'Bold ✓' : 'Bold'}
</button>
<button onClick={() => insertHeading(2)}>H2</button>
<button onClick={undo} disabled={!canUndo}>Undo</button>
<button onClick={redo} disabled={!canRedo}>Redo</button>
<div
ref={editorRef}
contentEditable
suppressContentEditableWarning
onFocus={() => setFocus(true)}
onBlur={() => setFocus(false)}
style={{ minHeight: 160, border: isFocused ? '2px solid #3b82f6' : '1px solid #ccc' }}
/>
<pre>{JSON.stringify(content, null, 2)}</pre>
</>
)
}
useRichContent() returns:
servicecontentstateisFocusedcanUndocanRedoselectedFormatsselectionisDirtyinsertTextinsertParagraphinsertHeadinginsertImageuploadImageinsertMentioninsertListtoggleMarkdeleteContentundoredoclearHistoryfocussetFocusgetPlainTextsetSelection
Provider pattern
function RichEditor() {
return (
<RichContentProvider config={{ placeholder: 'Write something…' }}>
<Toolbar />
</RichContentProvider>
)
}
function Toolbar() {
const { service } = useRichContentContext()
return <button onClick={() => service.toggleMark('bold')}>Bold</button>
}