Skip to content

mdadul/expo-rte

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

23 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Expo Rich Text Editor (expo-rte)

Expo RTE License Version Downloads

A cross-platform rich text editor for React Native and Expo applications

Features β€’ Installation β€’ Quick Start β€’ API β€’ Examples β€’ Contributing


expo-rte

✨ Features

  • πŸ› οΈ Highly Customizable - Adaptive toolbar with multiple density options
  • 🌍 Cross-Platform - Works seamlessly on iOS and Android
  • β™Ώ Accessible - WCAG compliant with proper ARIA labels
  • 🎯 Multiple Toolbar Styles - Basic, custom styled, and responsive adaptive toolbars
  • πŸ”„ Format Toggle - Smart formatting state management
  • πŸ“ Rich Formatting - Bold, italic, underline, strikethrough, lists, links, and more

πŸš€ Installation

# npm
npm install expo-rte

# yarn
yarn add expo-rte

# pnpm
pnpm add expo-rte

Development Build

For Expo development builds or bare React Native apps, you'll need to rebuild your app after installing:

# For Expo development builds
npx expo run:ios
npx expo run:android

# For bare React Native
npx react-native run-ios
npx react-native run-android

Note: This library requires a development build and will not work with Expo Go.

πŸ“± Quick Start

Basic Usage

import React, { useRef } from 'react';
import { View } from 'react-native';
import { RichTextEditor, RichTextEditorRef } from 'expo-rte';

export default function App() {
  const editorRef = useRef<RichTextEditorRef>(null);

  const handleContentChange = ({ nativeEvent }) => {
    console.log('Content:', nativeEvent.content);
  };

  return (
    <View style={{ flex: 1, padding: 20 }}>
      <RichTextEditor
        ref={editorRef}
        content="<p>Start typing...</p>"
        placeholder="Enter your text here..."
        onChange={handleContentChange}
        style={{ height: 300 }}
      />
    </View>
  );
}

Advanced Usage with Custom Toolbar

import React, { useRef } from 'react';
import { View } from 'react-native';
import { RichTextEditor, RichTextEditorRef, ToolbarConfig } from 'expo-rte';

const customToolbarConfig: ToolbarConfig = {
  adaptive: true,
  groupButtons: true,
  density: 'comfortable',
  scrollable: true,
  showLabels: true,
  buttons: [
    { type: 'bold', icon: 'B', label: 'Bold', group: 'format' },
    { type: 'italic', icon: 'I', label: 'Italic', group: 'format' },
    { type: 'underline', icon: 'U', label: 'Underline', group: 'format' },
    { type: 'bullet', icon: 'β€’', label: 'Bullet List', group: 'list' },
    { type: 'numbered', icon: '1.', label: 'Numbered List', group: 'list' },
    { type: 'link', icon: 'πŸ”—', label: 'Link', value: 'https://example.com', group: 'insert' },
    { type: 'undo', icon: 'β†Ά', label: 'Undo', group: 'action' },
    { type: 'redo', icon: 'β†·', label: 'Redo', group: 'action' },
  ],
};

export default function AdvancedEditor() {
  const editorRef = useRef<RichTextEditorRef>(null);

  return (
    <View style={{ flex: 1, padding: 20 }}>
      <RichTextEditor
        ref={editorRef}
        content="<p><strong>Rich</strong> <em>text</em> editor with <u>custom</u> toolbar!</p>"
        toolbarConfig={customToolbarConfig}
        style={{ height: 400 }}
      />
    </View>
  );
}

πŸ“š API Reference

RichTextEditor Props

Prop Type Default Description
content string "" Initial HTML content
placeholder string "" Placeholder text
editable boolean true Whether the editor is editable
showToolbar boolean true Whether to show the toolbar
toolbarConfig ToolbarConfig undefined Custom toolbar configuration
customToolbar ReactNode undefined Completely custom toolbar component
style ViewStyle undefined Container style
onChange function undefined Content change callback

RichTextEditorRef Methods

interface RichTextEditorRef {
  setContent: (content: string) => Promise<void>;
  getContent: () => Promise<string>;
  format: (type: FormatType, value?: any) => Promise<void>;
  undo: () => Promise<void>;
  redo: () => Promise<void>;
}

ToolbarConfig

interface ToolbarConfig {
  buttons?: ToolbarButton[];           // Custom button array
  style?: ViewStyle;                   // Toolbar container styling
  buttonStyle?: ViewStyle;             // Individual button styling
  buttonTextStyle?: TextStyle;         // Button text styling
  scrollable?: boolean;                // Enable horizontal scrolling
  showLabels?: boolean;                // Show button labels
  groupButtons?: boolean;              // Group buttons by category
  adaptive?: boolean;                  // Auto-adapt to screen size
  compactMode?: boolean;               // Use compact layout
  maxButtons?: number;                 // Max buttons for adaptive mode
  density?: 'comfortable' | 'compact' | 'dense'; // Button density
}

ToolbarButton

interface ToolbarButton {
  type: FormatType;                    // Button action type
  icon: string | ReactNode;            // Button icon (text or component)
  label?: string;                      // Optional label text
  value?: any;                         // Optional value (e.g., for links)
  group?: 'format' | 'list' | 'action' | 'insert'; // Button grouping
}

Format Types

type FormatType = 
  | 'bold' 
  | 'italic' 
  | 'underline' 
  | 'strikethrough' 
  | 'bullet' 
  | 'numbered' 
  | 'link' 
  | 'undo' 
  | 'redo';

🎨 Toolbar Customization

Responsive Toolbar

const responsiveConfig: ToolbarConfig = {
  adaptive: true,
  density: 'comfortable',
  scrollable: true,
  groupButtons: true,
  maxButtons: 8,
  buttons: [
    { type: 'bold', icon: 'B', label: 'Bold', group: 'format' },
    { type: 'italic', icon: 'I', label: 'Italic', group: 'format' },
    { type: 'underline', icon: 'U', label: 'Underline', group: 'format' },
    { type: 'bullet', icon: 'β€’', label: 'Bullets', group: 'list' },
    { type: 'numbered', icon: '1.', label: 'Numbers', group: 'list' },
    { type: 'undo', icon: 'β†Ά', label: 'Undo', group: 'action' },
    { type: 'redo', icon: 'β†·', label: 'Redo', group: 'action' },
  ],
};

Custom Styled Toolbar

const customConfig: ToolbarConfig = {
  buttons: [
    { type: 'bold', icon: '𝐁', label: 'Bold' },
    { type: 'italic', icon: '𝐼', label: 'Italic' },
    { type: 'link', icon: 'πŸ”—', label: 'Link', value: 'https://example.com' },
  ],
  buttonStyle: {
    backgroundColor: '#007AFF',
    borderRadius: 8,
    paddingHorizontal: 12,
  },
  buttonTextStyle: {
    color: '#ffffff',
    fontWeight: '600',
  },
  showLabels: true,
  density: 'comfortable',
};

πŸ“š Documentation Examples

For comprehensive examples and real-world usage patterns, see our Examples Documentation:

Quick Example

import React, { useRef } from 'react';
import { View } from 'react-native';
import { RichTextEditor, RichTextEditorRef, ToolbarConfig } from 'expo-rte';

const customConfig: ToolbarConfig = {
  adaptive: true,
  density: 'comfortable',
  buttons: [
    { type: 'bold', icon: 'B', label: 'Bold' },
    { type: 'italic', icon: 'I', label: 'Italic' },
    { type: 'undo', icon: 'β†Ά', label: 'Undo' },
  ],
};

export default function MyEditor() {
  const editorRef = useRef<RichTextEditorRef>(null);

  return (
    <View style={{ flex: 1, padding: 20 }}>
      <RichTextEditor
        ref={editorRef}
        toolbarConfig={customConfig}
        placeholder="Start writing..."
        style={{ height: 300 }}
      />
    </View>
  );
}

πŸ“± Responsive Design

The editor automatically adapts to different screen sizes:

  • πŸ“± Small screens (<400px): Compact buttons, essential formatting only
  • πŸ’» Regular screens (400-768px): Standard button sizes, full toolbar
  • πŸ“Š Tablets (768px+): Larger touch targets, more spacing

Manual Responsive Configuration

const responsiveConfig: ToolbarConfig = {
  adaptive: true,
  density: 'comfortable', // 'comfortable' | 'compact' | 'dense'
  maxButtons: 6, // Limit buttons on small screens
  scrollable: true, // Enable scrolling when needed
};

πŸ”§ Advanced Features

Content Import/Export

// Set rich content
await editorRef.current?.setContent(`
  <h1>My Document</h1>
  <p>This is <strong>bold</strong> and <em>italic</em> text.</p>
  <ul>
    <li>Bullet point 1</li>
    <li>Bullet point 2</li>
  </ul>
`);

// Get HTML content
const htmlContent = await editorRef.current?.getContent();

Undo/Redo

// Programmatic undo/redo
await editorRef.current?.undo();
await editorRef.current?.redo();

πŸ› οΈ Customization

Custom Button Icons

import { MaterialIcons } from '@expo/vector-icons';

const customButtons: ToolbarButton[] = [
  {
    type: 'bold',
    icon: <MaterialIcons name="format-bold" size={20} color="#333" />,
    label: 'Bold'
  },
  // ... more buttons with custom icons
];

Styling

const customStyle = {
  container: {
    borderRadius: 12,
    backgroundColor: '#f5f5f5',
  },
  toolbar: {
    backgroundColor: '#ffffff',
    borderBottomColor: '#e0e0e0',
  },
  button: {
    backgroundColor: '#007AFF',
    borderRadius: 8,
  },
  buttonText: {
    color: '#ffffff',
    fontWeight: '600',
  }
};

<RichTextEditor
  style={customStyle.container}
  toolbarConfig={{
    style: customStyle.toolbar,
    buttonStyle: customStyle.button,
    buttonTextStyle: customStyle.buttonText,
  }}
/>

πŸ› Troubleshooting

Common Issues

  1. Editor not appearing: Ensure you're using a development build, not Expo Go
  2. Formatting not working: Check that the toolbar is enabled and buttons are configured
  3. Content not updating: Verify the onChange callback is properly connected
  4. Performance issues: Consider using adaptive: true for better performance on lower-end devices

Debug Mode

// Enable debug logging
<RichTextEditor
  onChange={({ nativeEvent }) => {
    console.log('Content changed:', nativeEvent.content);
  }}
/>

🀝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

# Clone the repository
git clone https://github.com/mdadul/expo-rte.git
cd expo-rte

# Install dependencies
npm install

# Run the example app
cd example
npm install
npx expo run:ios # or npx expo run:android

Running Tests

npm test

Building

npm run build

πŸ“„ License

MIT License - see the LICENSE file for details.

⬆ Back to top

Made with ❀️ by Emdadul Islam

About

A cross-platform rich text editor for React Native and Expo applications

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors