@pawanosman/texteditor
v1.0.1
Published
Advanced text editor React component library with syntax highlighting, custom overlays, and extensive customization options
Maintainers
Readme
@pawanosman/texteditor
An advanced, feature-rich text editor React component library with syntax highlighting, custom overlays, grammar checking support, and extensive customization options.
📦 Installation
npm install @pawanosman/texteditor
# or
yarn add @pawanosman/texteditor
# or
pnpm add @pawanosman/texteditor✨ Features
- 🎨 Multiple Editor Modes - Support for plaintext, markdown, code, HTML, CSS, and JSON
- 🌈 Syntax Highlighting - Built-in support for 25+ programming languages using PrismJS
- ✏️ Rich Text Editing - Full Markdown support with toolbar buttons for formatting
- 🎯 Custom Highlights - Add highlights with actions (errors, warnings, suggestions, etc.)
- 🔲 Custom Overlays - Create custom overlay regions with interactive elements
- 📝 Grammar-Style Highlights - Built-in support for spelling, grammar, clarity, and tone suggestions
- 🎛️ Customizable Toolbar - Show/hide built-in buttons or add custom toolbar actions
- 🌓 Theme Support - Dark, light, and auto (system preference) themes
- 📏 Line Numbers - Optional line number display
- 🔍 Find & Replace - Built-in find and replace functionality
- ⌨️ Keyboard Shortcuts - Comprehensive keyboard shortcut support
- 🌐 RTL Support - Full right-to-left text direction support
- 🎨 Font Configuration - Customize font family, size, weight, and more
- 📱 Responsive Design - Works seamlessly on desktop and mobile devices
- ♿ Accessibility - Built with accessibility in mind
📦 Installation
npm install @pawanosman/texteditor
# or
yarn add @pawanosman/texteditor
# or
pnpm add @pawanosman/texteditor🚀 Quick Start
import React, { useState } from 'react';
import { TextEditor } from '@pawanosman/texteditor';
import '@pawanosman/texteditor/styles.css';
function App() {
const [value, setValue] = useState('// Start coding...\nconsole.log("Hello World!");');
return (
<TextEditor
value={value}
onChange={setValue}
mode="code"
language="javascript"
minHeight={400}
theme="dark"
/>
);
}📖 API Reference
Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| value | string | - | Controlled editor value |
| defaultValue | string | "" | Initial value for uncontrolled editor |
| onChange | (value: string) => void | - | Called when editor content changes |
| mode | EditorMode | "plaintext" | Editor mode (plaintext, markdown, code, html, css, json) |
| language | CodeLanguage | "javascript" | Programming language for syntax highlighting (when mode is "code") |
| highlights | Highlight[] | - | Array of highlights to display |
| onHighlightsChange | (highlights: Highlight[]) => void | - | Called when highlights change |
| overlays | CustomOverlay[] | - | Array of custom overlays to display |
| onOverlaysChange | (overlays: CustomOverlay[]) => void | - | Called when overlays change |
| placeholder | string | "Start typing..." | Placeholder text |
| readOnly | boolean | false | Make editor read-only |
| disabled | boolean | false | Disable editor |
| minHeight | number \| string | 200 | Minimum height of editor |
| maxHeight | number \| string | - | Maximum height of editor |
| showLineNumbers | boolean | true | Show line numbers |
| showToolbar | boolean | true | Show toolbar |
| showStatusBar | boolean | true | Show status bar |
| renderInlineFormatting | boolean | true | Render inline formatting in markdown mode |
| toolbarConfig | ToolbarConfig | - | Toolbar configuration |
| direction | TextDirection | "ltr" | Text direction (ltr, rtl, auto) |
| fontConfig | FontConfig | - | Font configuration |
| theme | ThemeMode | "dark" | Theme mode (light, dark, auto) |
| className | string | - | Additional CSS class |
| style | React.CSSProperties | - | Additional inline styles |
Ref API
The editor exposes methods through a ref:
import { useRef } from 'react';
import { TextEditor, TextEditorRef } from '@pawanosman/texteditor';
const editorRef = useRef<TextEditorRef>(null);
// Methods
editorRef.current?.getValue(); // Get current value
editorRef.current?.setValue('new value'); // Set value
editorRef.current?.insertText('text'); // Insert text at cursor
editorRef.current?.getSelection(); // Get selection range
editorRef.current?.setSelection(start, end); // Set selection
editorRef.current?.focus(); // Focus editor
editorRef.current?.blur(); // Blur editor
editorRef.current?.addHighlight(highlight); // Add highlight
editorRef.current?.removeHighlight(id); // Remove highlight
editorRef.current?.clearHighlights(); // Clear all highlights
editorRef.current?.addOverlay(overlay); // Add overlay
editorRef.current?.removeOverlay(id); // Remove overlay
editorRef.current?.clearOverlays(); // Clear all overlays
editorRef.current?.setMode(mode); // Set editor mode
editorRef.current?.setLanguage(language); // Set language🎨 Editor Modes
Code Mode
<TextEditor
mode="code"
language="typescript"
value="// Your TypeScript code..."
/>Supported languages: javascript, typescript, python, java, csharp, cpp, c, go, rust, ruby, php, swift, kotlin, sql, html, css, scss, json, yaml, xml, markdown, bash, shell, powershell, dockerfile, plaintext
Markdown Mode
<TextEditor
mode="markdown"
value="# Hello\nThis is **bold** text."
/>Other Modes
<TextEditor mode="html" />
<TextEditor mode="css" />
<TextEditor mode="json" />
<TextEditor mode="plaintext" />🎯 Highlights
Highlights allow you to mark regions of text with different styles and optional actions:
import { Highlight } from '@pawanosman/texteditor';
const [highlights, setHighlights] = useState<Highlight[]>([
{
id: 'error-1',
start: 10,
end: 20,
type: 'error',
message: 'Syntax error',
description: 'Unexpected token',
suggestion: 'Fix the syntax',
actions: [
{
label: 'Fix',
onClick: (highlight) => console.log('Fixing', highlight),
variant: 'primary'
}
]
}
]);
<TextEditor
highlights={highlights}
onHighlightsChange={setHighlights}
/>Highlight Types
highlight- General yellow highlighterror- Red error highlightwarning- Orange warning highlightsuccess- Green success highlightinfo- Blue info highlightspelling- Spelling mistake (red)grammar- Grammar error (red)punctuation- Punctuation issue (red)clarity- Clarity suggestion (blue)conciseness- Conciseness suggestion (blue)readability- Readability issue (blue)vocabulary- Vocabulary improvement (green)engagement- Engagement suggestion (green)tone- Tone adjustment (purple)formality- Formality level (purple)politeness- Politeness suggestion (purple)inclusive- Inclusive language (purple)
🔲 Custom Overlays
Overlays provide more customization than highlights:
import { CustomOverlay } from '@pawanosman/texteditor';
const [overlays, setOverlays] = useState<CustomOverlay[]>([
{
id: 'overlay-1',
start: 50,
end: 100,
className: 'my-custom-overlay',
style: {
background: 'rgba(168, 85, 247, 0.3)',
borderBottom: '2px dashed #a855f7'
},
title: 'AI Suggestion',
description: 'Consider improving this section',
actions: [
{
label: 'Accept',
onClick: (overlay) => console.log('Accepted', overlay)
}
],
onClick: (overlay, event) => console.log('Clicked', overlay)
}
]);
<TextEditor
overlays={overlays}
onOverlaysChange={setOverlays}
/>🎛️ Toolbar Customization
Hide/Show Built-in Buttons
const toolbarConfig: ToolbarConfig = {
visibleButtons: ['bold', 'italic', 'underline'], // Only show these
// or
hiddenButtons: ['strikethrough', 'codeblock'], // Hide these
showGroupSeparators: true
};
<TextEditor toolbarConfig={toolbarConfig} />Available built-in buttons: undo, redo, bold, italic, underline, strikethrough, code, codeblock, link, image, quote, list, numbered-list, task-list, heading1, heading2, heading3, horizontal-rule, indent, outdent, highlight, error-highlight, clear-highlights, find-replace, table
Add Custom Buttons
const toolbarConfig: ToolbarConfig = {
customButtons: [
{
id: 'timestamp',
label: 'Timestamp',
tooltip: 'Insert current timestamp',
icon: <ClockIcon />,
group: 'custom',
action: (context) => {
const timestamp = new Date().toISOString();
context.setValue(
context.value.substring(0, context.selection.end) +
timestamp +
context.value.substring(context.selection.end)
);
},
disabled: (context) => context.readOnly,
active: (context) => false
}
]
};🎨 Theming
Built-in Themes
<TextEditor theme="dark" /> // Dark theme (default)
<TextEditor theme="light" /> // Light theme
<TextEditor theme="auto" /> // Follow system preferenceCustom CSS Variables
You can customize the appearance using CSS variables:
.te-editor-container {
--te-bg-primary: #0a0a0b;
--te-bg-secondary: #18181b;
--te-bg-tertiary: #27272a;
--te-border: #3f3f46;
--te-text-primary: #fafafa;
--te-text-secondary: #a1a1aa;
--te-text-tertiary: #71717a;
--te-accent: #3b82f6;
--te-accent-hover: #2563eb;
--te-font-mono: 'JetBrains Mono', monospace;
--te-font-sans: 'Inter', sans-serif;
--te-font-size: 13px;
--te-line-height: 1.6;
}🎨 Font Configuration
const fontConfig: FontConfig = {
fontFamily: '"JetBrains Mono", monospace',
fontSize: 14,
fontWeight: 400,
lineHeight: 1.6,
letterSpacing: '0.5px',
fontStyle: 'normal',
uiFontFamily: '"Inter", sans-serif'
};
<TextEditor fontConfig={fontConfig} />⌨️ Keyboard Shortcuts
| Shortcut | Action |
|----------|--------|
| Ctrl + Z | Undo |
| Ctrl + Y | Redo |
| Ctrl + B | Bold |
| Ctrl + I | Italic |
| Ctrl + U | Underline |
| Ctrl + E | Inline Code |
| Ctrl + K | Link |
| Ctrl + F | Find/Replace |
| Ctrl + Shift + S | Strikethrough |
| Ctrl + Shift + K | Code Block |
| Ctrl + Shift + Q | Quote |
| Ctrl + Shift + U | List |
| Ctrl + Shift + O | Numbered List |
| Escape | Close panels/popups |
🌍 RTL Support
<TextEditor direction="rtl" /> // Right-to-left
<TextEditor direction="ltr" /> // Left-to-right (default)
<TextEditor direction="auto" /> // Auto-detect📝 Examples
Grammar Checker Integration
function GrammarCheckerEditor() {
const [highlights, setHighlights] = useState<Highlight[]>([]);
const checkGrammar = async (text: string) => {
const results = await grammarService.check(text);
const newHighlights = results.map(error => ({
id: `grammar-${error.id}`,
start: error.start,
end: error.end,
type: error.type, // 'spelling', 'grammar', 'clarity', etc.
message: error.message,
suggestion: error.suggestion,
suggestions: error.alternatives
}));
setHighlights(newHighlights);
};
return (
<TextEditor
highlights={highlights}
onHighlightsChange={setHighlights}
onChange={checkGrammar}
/>
);
}AI-Powered Writing Assistant
function AIWritingAssistant() {
const [overlays, setOverlays] = useState<CustomOverlay[]>([]);
const addAISuggestion = (selection: { start: number, end: number }) => {
const overlay: CustomOverlay = {
id: `ai-${Date.now()}`,
start: selection.start,
end: selection.end,
className: 'ai-suggestion',
title: 'AI Suggestion',
description: 'Click to see AI-powered improvements',
actions: [
{
label: 'Improve',
variant: 'primary',
onClick: async (overlay) => {
const improved = await aiService.improve(text);
// Apply improvement...
}
}
]
};
setOverlays(prev => [...prev, overlay]);
};
return <TextEditor overlays={overlays} />;
}Collaborative Editor
function CollaborativeEditor() {
const [cursors, setCursors] = useState<UserCursor[]>([]);
const [highlights, setHighlights] = useState<Highlight[]>([]);
// Simulate remote user selections
useEffect(() => {
socket.on('user-selection', (user: User) => {
const overlay: CustomOverlay = {
id: `cursor-${user.id}`,
start: user.selection.start,
end: user.selection.end,
className: 'remote-cursor',
style: {
backgroundColor: user.color,
opacity: 0.3
},
title: user.name
};
setOverlays(prev => [...prev.filter(o => !o.id.startsWith(`cursor-${user.id}`)), overlay]);
});
}, []);
return <TextEditor overlays={overlays} />;
}🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
📄 License
MIT © Pawan Osman
🙏 Acknowledgments
📚 More Examples
For more comprehensive examples, check out our Examples Page or run the demo locally:
git clone https://github.com/PawanOsman/TextEditor.git
cd TextEditor
npm install
npm run devMade with ❤️ by Pawan Osman
