Skip to main content

Basic Extension Usage

Extension Structure

Example Extension

Here's the complete structure of an extension file:

import { defineExtension } from '@howljs/tiptap-native/extension';
import TextAlign, { type TextAlignOptions } from '@tiptap/extension-text-align';

declare module '@howljs/tiptap-native' {
interface ExtensionMap {
TextAlign: TextAlignOptions;
}
interface ExtensionStates {
isTextAlignCenter: boolean;
isTextAlignLeft: boolean;
isTextAlignRight: boolean;
isTextAlignJustify: boolean;
canTextAlignCenter: boolean;
canTextAlignLeft: boolean;
canTextAlignRight: boolean;
canTextAlignJustify: boolean;
}
interface ExtensionCommands {
setTextAlign: {
alignment: 'center' | 'left' | 'right' | 'justify';
};
unsetTextAlign: undefined;
toggleTextAlign?: {
alignment: 'center' | 'left' | 'right' | 'justify';
};
}
}

export default defineExtension(TextAlign, {
defaultOptions: {
types: ['heading', 'paragraph'],
},
commands: {
setTextAlign: (editor, params) =>
editor.chain().focus().setTextAlign(params.alignment).run(),
unsetTextAlign: (editor) => editor.chain().focus().unsetTextAlign().run(),
toggleTextAlign: (editor, params) =>
editor
.chain()
.focus()
.toggleTextAlign(params?.alignment ?? 'left')
.run(),
},
states: {
isTextAlignCenter: (editor) => editor.isActive({ textAlign: 'center' }),
isTextAlignLeft: (editor) => editor.isActive({ textAlign: 'left' }),
isTextAlignRight: (editor) => editor.isActive({ textAlign: 'right' }),
isTextAlignJustify: (editor) => editor.isActive({ textAlign: 'justify' }),
canTextAlignCenter: (editor) => editor.can().toggleTextAlign('center'),
canTextAlignLeft: (editor) => editor.can().toggleTextAlign('left'),
canTextAlignRight: (editor) => editor.can().toggleTextAlign('right'),
canTextAlignJustify: (editor) => editor.can().toggleTextAlign('justify'),
},
});

Module Declaration

The declare module '@howljs/tiptap-native' is how you define new extensions and extend the library's type system.

ExtensionMap Interface

The ExtensionMap interface defines new extensions. It's an object where the key is the extension name (the filename in the tiptap-native/extensions folder) and the value is the extension's options.

Example:

File: tiptap-native/extensions/TextAlign.ts

interface ExtensionMap {
TextAlign: TextAlignOptions;
}

Once defined, you can use the new TextAlign extension by declaring it in the EditorProvider:

<EditorProvider extensions={[{name: 'TextAlign', options: {}}]}>
<EditorContent />
</EditorProvider>

ExtensionStates Interface

The ExtensionStates interface defines the states of an extension. It's an object where the key is the state name and the value is the data type returned.

Example:

interface ExtensionStates {
isTextAlignCenter: boolean;
}

Now when you use useEditorState, you can access the extension's state like this:

const isTextAlignCenter = useEditorState({
selector: (state) => state.isTextAlignCenter,
});

ExtensionCommands Interface

The ExtensionCommands interface defines the commands of an extension. It's an object where the key is the command name and the value is the command parameters.

Example:

interface ExtensionCommands {
unsetTextAlign: undefined;
setTextAlign: {
alignment: 'center' | 'left' | 'right' | 'justify';
};
}

Now you can use useEditorCommands to call the extension's commands:

const { execute } = useEditorCommands();

// With parameters
execute({command: 'setTextAlign', params: {alignment: 'center'}});

// Without parameters
execute('unsetTextAlign');
execute({command: 'unsetTextAlign'});

defineExtension Function

The defineExtension function is used to define an extension. It takes an extension and returns a defined extension with the following properties:

  • defaultOptions: Default options for the extension
  • commands: Commands of the extension
  • states: States of the extension

Key Concepts Summary

  1. Module Declaration: Extends TypeScript types for your extension
  2. ExtensionMap: Registers your extension with the library
  3. ExtensionStates: Defines what state information your extension provides
  4. ExtensionCommands: Defines what actions your extension can perform
  5. defineExtension: Wraps your TipTap extension with React Native functionality

This structure allows you to create fully integrated extensions that work seamlessly with the TipTap Native bridge, providing both state management and command execution capabilities.