TenTap Editor

repository·main·Indexed 22 days ago

https://github.com/10play/10tap-editor

A highly customizable and extendable rich text editor for React Native applications, built on Tiptap and ProseMirror. It features a native toolbar, support for dynamic schemes, and compatibility with the React Native New Architecture (version 0.73.5+). The library provides the RichText component, useEditorBridge hook, and various BridgeExtensions for adding features like text styling, lists, and media handling.

Tokens
21.5K
Snippets
66
Records
95
Agent score
78%

What's inside @10play/tentap-editor

  1. Overview of TenTap Editor features

    main

    TenTap is a typed, customizable, and extendable Rich Text editor for React Native, built on top of Tiptap and ProseMirror.

    Key Features:

    • Based on Tiptap
    • Extendable architecture
    • Support for dynamic schemes
    • Native toolbar support
    • Customizable styles and theme support (including Dark mode)
    • Supports React Native New Architecture (requires React Native version 0.73.5 or above)
  2. What is BridgeState and how to use it

    main

    The BridgeState represents the latest state of the editor webview as seen from the native side. It is an extendable interface that aggregates properties from various BridgeExtensions.

    To access and subscribe to changes in the BridgeState within a React component, use the useBridgeState hook. This hook provides the current state and the EditorBridge instance.

  3. Use EditorBridge to control the editor from React Native

    main

    The EditorBridge is the primary interface for executing commands on the editor from the React Native side. It provides a set of methods to manipulate content, formatting, and editor state.

    When using tentapStarterKit, the EditorBridge comes pre-extended with various bridges (like CoreBridge, HistoryBridge, LinkBridge, etc.), providing a comprehensive set of capabilities including text formatting, history management, and content retrieval.

    Note that the available methods on the EditorBridge instance depend on which bridges are included in your setup.

  4. Understand the core architecture: EditorBridge and bridgeExtensions

    main

    The 10tap-editor architecture relies on two primary abstractions to facilitate communication between the native mobile environment and the webview-based editor:

    1. EditorBridge: A bridge used to control the editor from the native side.
    2. bridgeExtension: A typed class that enables communication between the native part and the webview part. These extensions are used to implement specific editor functionalities (like bold, italic, or image insertion).

    By passing a specific list of bridgeExtensions to the editor, you can control the editor's capabilities and schema. For example, in a chat application where you want to restrict formatting, you can omit certain extensions (like Underline) to ensure that even pasted text will not include that specific formatting.

  5. Use 10tap-editor in Advanced mode

    main

    Advanced usage is required if you need to:

    1. Add your own custom Tiptap extensions.
    2. Build your own custom bridgeExtension.

    In Advanced mode, you must bundle the web editor yourself to gain full control over the code running inside the webview. The library provides specific utils, components, and hooks to help you customize the editor while still leveraging the core features and fixes provided by tentap.

    For detailed instructions, refer to the Advanced Setup guide.

  6. Position the iOS Toolbar above a React Navigation header

    main

    When using react-navigation headers on iOS, the Toolbar might appear underneath the keyboard instead of directly above it. To fix this, you must configure the KeyboardAvoidingView with a keyboardVerticalOffset and apply paddingBottom to the RichText container.

    1. Calculate keyboardVerticalOffset: Set this to the sum of the top safe area inset (from useSafeAreaInsets) and the header height. On iOS, the standard header height used in this context is 38.
    2. Configure KeyboardAvoidingView: Pass the calculated offset to the keyboardVerticalOffset prop, but only when Platform.OS === 'ios'.
    3. Prevent text overlap: Add paddingBottom to the container holding the <RichText /> component (on iOS only) equal to the header height. This ensures the text does not disappear behind the toolbar while typing.
    const HEADER_HEIGHT = 38; // IOS Only
    
    const { top } = useSafeAreaInsets();
    const keyboardVerticalOffset = HEADER_HEIGHT + top;
    
    // ... inside component
    
    <View style={exampleStyles.contentContainer}>
      <RichText editor={editor} />
    </View>
    
    <KeyboardAvoidingView
      behavior={'padding'}
      style={exampleStyles.keyboardAvoidingView}
      keyboardVerticalOffset={Platform.OS === 'ios' ? keyboardVerticalOffset : undefined}
    >
      <Toolbar editor={editor} />
    </KeyboardAvoidingView>
    
    // ... styles
    
    const exampleStyles = StyleSheet.create({
      contentContainer: {
        flex: 1,
        paddingBottom: Platform.OS === 'ios' ? HEADER_HEIGHT : 0,
      },
      keyboardAvoidingView: {
        position: 'absolute',
        width: '100%',
        bottom: 0,
      },
    });
  7. Override Bridge CSS using configureCSS

    main

    You can override or add custom CSS to a specific bridge during initialization using the configureCSS method. This method is called on the bridge object (e.g., CodeBridge.configureCSS(cssString)).

    Important: When using bridgeExtensions, ensure you spread the TenTapStartKit before your extended plugins, as duplicate plugins will be ignored.

    Note that calling configureCSS more than once on the same bridge will override the previous CSS configuration.

    const customCodeBlockCSS = `
    code {
        background-color: #ffdede;
        border-radius: 0.25em;
        border-color: #e45d5d;
        border-width: 1px;
        border-style: solid;
        box-decoration-break: clone;
        color: #cd4242;
        font-size: 0.9rem;
        padding: 0.25em;
    }
    `;
    const editor = useEditorBridge({
      // ... other config
      bridgeExtensions: [
        // It is important to spread StarterKit BEFORE our extended plugin,
        // as plugin duplicated will be ignored
        ...TenTapStartKit,
        CodeBridge.configureCSS(customCodeBlockCSS),
      ],
    });
  8. Set up the website for local development

    main

    The website is built with Docusaurus. To set up the development environment, install dependencies using yarn, then start the local development server with yarn start. The server supports live reloading for most changes.

    $ yarn
    $ yarn start