Package Exports
- react-textflux
- react-textflux/dist/react-textflux.css
Readme
React Textflux
🚀 What's New
- Production ready: All major bugs fixed, UX polished
- Mention dropdown: Keyboard navigation auto-scrolls, dark/light theme highlight, visible text always
- Media skeleton loader: Shows animated skeleton while uploading/inserting images/videos
- Unified media handling: Paste, drag-and-drop, and toolbar all use the same upload logic
- Accessibility: All dropdowns and toolbars are keyboard accessible
- CSS isolation: All classes prefixed with
tf-(no conflicts) - Media fullscreen control: You can now control whether images/videos are clickable for fullscreen preview using the
mediaFullscreenprop on the Editor component. - Smart cursor positioning: Cursor automatically moves to the end after inserting media, mentions, or emojis
- Improved button reliability: Fixed image/video insert buttons that sometimes didn't work
- Enhanced error handling: Better error handling for file operations and media uploads
- Focus management: Improved focus handling between editor and toolbar
- Existing media support: All existing images/videos in editor content are automatically clickable for fullscreen preview
- Code block support: Insert code blocks via toolbar or Ctrl+K, and paste code from IDE for auto-formatting
A minimal, modular, and customizable React rich text editor component with:
- Basic formatting (bold, italic, underline, strikethrough, blockquote, lists)
- @mention with profile pic/initials
- Emoji picker (hundreds of emojis)
- Media rendering (image/video) with fullscreen preview
- Code block support with text wrapping and monospace font
- Dark/light theme support
- Custom upload logic via callback
- No CSS framework dependency (pure CSS, all classes prefixed with
tf-for isolation) - Optional fullscreen media preview
- Smart cursor positioning for seamless writing experience
- Existing media support for fullscreen preview
Code Block Support
- Insert code blocks using the toolbar button (</>) or keyboard shortcut
Ctrl+K(Cmd+K on Mac) - Paste code from any IDE and it will auto-format as a code block
- Text wrapping and horizontal scroll for long lines
- Monospace font for code clarity
- Continue typing after code: After pasting/inserting code, a new line is added so you can keep writing
- Highlighting: Toolbar button is highlighted when your cursor is inside a code block
Install
npm install react-textfluxUsage
// Only default import is supported:
import Editor from 'react-textflux';
import "react-textflux/dist/react-textflux.css";
function App() {
// Example: controlled usage with backend value
const [description, setDescription] = React.useState('');
// Simulate fetching from backend
React.useEffect(() => {
// fetch description from backend
setTimeout(() => setDescription('<p>Initial <b>description</b> from backend</p>'), 1000);
}, []);
// Example: custom upload logic (S3, base64, etc.)
const handleMediaUpload = async (file, type) => {
// Upload file to your server or S3, return { url, type, name }
// Or fallback to base64:
const toBase64 = file => new Promise((res, rej) => {
const reader = new FileReader();
reader.onload = () => res(reader.result);
reader.onerror = rej;
reader.readAsDataURL(file);
});
const url = await toBase64(file);
return { url, type, name: file.name };
};
// Example: mention data
const mentions = [
{ id: 1, name: 'John Doe', profile_pic: 'https://example.com/john.jpg' },
{ id: 2, name: 'Jane Smith', profile_pic: 'https://example.com/jane.jpg' },
{ id: 3, name: 'Bob Johnson' } // without profile_pic
];
// Example: custom API call and clear on Enter
const handleEnter = async (e) => {
// 1. API call
await fetch('/your-api', { method: 'POST', body: JSON.stringify({ content: description }) });
// 2. Clear editor (controlled mode)
setDescription('');
// (Uncontrolled: e.target.innerHTML = '';)
};
return (
<Editor
theme="light" // or "dark"
mentions={mentions}
onMediaUpload={handleMediaUpload}
value={description} // controlled value
onChange={setDescription} // updates state on any content change
mediaFullscreen={true} // <-- Add this line to enable fullscreen media preview
onEnter={handleEnter} // <-- Called when Enter is pressed
/>
);
}Note: The
valueprop makes the editor controlled, just like a textarea. Pass your HTML string tovalue, and update it viaonChange. All content changes (typing, media insert, mentions, formatting) will triggeronChangewith the latest HTML.
Note: The
onEnterprop is called whenever the user presses Enter in the editor. You can use it for custom actions like submitting, saving, or clearing the editor. In controlled mode, clear the editor by setting your value state to ''. In uncontrolled mode, usee.target.innerHTML = ''inside onEnter.
Media Fullscreen Preview
- Media Fullscreen Preview: Click any image or video in the editor to open a fullscreen overlay preview. Click the close (×) button or outside the media to exit preview.
- Works with all media: Both newly inserted and existing media (from database, etc.) are clickable for fullscreen preview when
mediaFullscreen={true}is enabled.
Tip: You can customize the fullscreen overlay style by editing the relevant CSS in the source.
Smart Cursor Positioning
The editor now automatically positions the cursor in the most logical place after various operations:
- Media Insertion: After inserting images/videos via toolbar, drag & drop, or paste, the cursor moves to the end so you can continue typing
- Mention Insertion: After selecting a mention from the dropdown, cursor moves to the end
- Emoji Insertion: After inserting an emoji, cursor moves to the end
- Seamless Writing: No more manual cursor positioning - just keep typing naturally
- Code Block Paste: After pasting code, a new line is added so you can keep typing outside the code block
Features
- Formatting: Bold, Italic, Underline, Strikethrough, Blockquote, Lists
- @Mention: User list with profile pic/initials, keyboard navigation, auto-scroll
- Emoji Picker: 200+ emojis, fast search, outside click to close
- Media: Render images/videos (upload logic is up to you), click to fullscreen preview
- Media Skeleton: Animated skeleton loader while uploading/inserting
- Code Block: Insert code blocks via toolbar or Ctrl+K, auto-format on paste, text wrapping, monospace font
- Theme: Light & dark mode (prop)
- Keyboard Shortcuts: Tooltips show shortcuts (e.g. Ctrl+B, Ctrl+K)
- Custom CSS: No Tailwind/Bootstrap required
- CSS Isolation: All classes prefixed with
tf-(no conflicts with other frameworks) - Dark Theme Polish: Selected toolbar/mention is deep blue for better contrast
- Emoji/Mention Scrollbar: Thin, theme-aware, and modern
- Accessibility: All dropdowns and toolbars are keyboard accessible
- Optional Media Fullscreen: Enable fullscreen preview for images/videos by setting
mediaFullscreen={true}on the Editor. If not set, media is not clickable by default. - Smart Cursor Positioning: Automatic cursor positioning after media, mention, emoji, and code block insertion
- Reliable Button Operation: Fixed image/video insert buttons for consistent functionality
- Enhanced Error Handling: Better error handling and debugging for file operations
- Existing Media Support: All existing images/videos in editor content automatically get fullscreen functionality
Keyboard Shortcuts
| Action | Shortcut |
|---|---|
| Bold | Ctrl+B / Cmd+B |
| Italic | Ctrl+I / Cmd+I |
| Underline | Ctrl+U / Cmd+U |
| Strikethrough | Ctrl+Shift+S / Cmd+Shift+S |
| Blockquote | Ctrl+Q / Cmd+Q |
| Ordered List | Ctrl+Shift+L / Cmd+Shift+L |
| Unordered List | Ctrl+Shift+U / Cmd+Shift+U |
| Code Block | Ctrl+K / Cmd+K |
Props
| Prop | Type | Default | Description |
|---|---|---|---|
theme |
string | 'light' | 'light' or 'dark' |
mentions |
array | [] | Array of user objects: [{id, name, profile_pic?}] |
onMediaUpload |
function | undefined | Custom upload handler: (file, type) => Promise<{url, type, name}> |
value |
string | undefined | Controlled value: HTML string to display in the editor. Use with onChange for controlled usage. |
onChange |
function | undefined | Called with latest HTML string on any content change (typing, media, mentions, formatting, etc). |
mediaFullscreen |
boolean | false | If true, images/videos are clickable and open in fullscreen overlay. If false or not set, media is not clickable. |
onEnter |
function | undefined | Called with the keyboard event when Enter is pressed in the editor. Use for custom submit, save, or clear logic. |
onEnter: API Call & Clear Example
Controlled mode:
<Editor
value={description}
onChange={setDescription}
onEnter={async () => {
await fetch('/api/save', { method: 'POST', body: JSON.stringify({ content: description }) });
setDescription(''); // clear editor
}}
/>Uncontrolled mode:
<Editor
onEnter={async (e) => {
await fetch('/api/save', { method: 'POST', body: JSON.stringify({ content: e.target.innerHTML }) });
e.target.innerHTML = '';
}}
/>Customization
- Mentions: Pass your user list as
mentionsprop - Emoji List: Edit
Toolbar.jsxemojis array - CSS: Edit
src/index.cssfor full style control (all classes usetf-prefix) - Toolbar/Theme: Update colors in
src/index.cssfor your brand - Media Fullscreen: Use the
mediaFullscreenprop to control whether media is clickable for fullscreen preview.
Troubleshooting
Image/Video Insert Buttons Not Working
- Fixed in latest version: The buttons now use proper event handling and should work reliably
- If issues persist, check browser console for error messages
- Ensure file input permissions are granted
[plugin:vite:import-analysis] Failed to resolve entry for package
- Make sure your
package.jsonhas correctmain,module, andexportsfields. - Both
dist/index.es.jsanddist/index.umd.jsmust exist after build.
React Context/JSX Runtime Errors
- Ensure your library's Vite config has:
external: [ 'react', 'react-dom', 'react/jsx-runtime', 'react/jsx-dev-runtime' ]
- And
output.globalsincludes:globals: { react: 'React', 'react-dom': 'ReactDOM', 'react/jsx-runtime': 'jsxRuntime', 'react/jsx-dev-runtime': 'jsxDevRuntime' }
- Consumer app and library must use the same React version.
Recent Bug Fixes
- ✅ Fixed image/video insert buttons - Now work reliably every time
- ✅ Improved cursor positioning - Automatically moves to end after media insertion
- ✅ Enhanced error handling - Better error handling for file operations
- ✅ Fixed focus management - Editor doesn't lose focus when clicking toolbar buttons
- ✅ Improved event handling - Better event propagation and button responsiveness
- ✅ Added existing media support - All existing images/videos in content are now clickable for fullscreen
- ✅ Code block paste/toolbar - Code blocks are now easy to insert, auto-format, and support text wrapping
License
MIT