Basic Extension Usage
Extension Structure
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 extensioncommands
: Commands of the extensionstates
: States of the extension
Key Concepts Summary
- Module Declaration: Extends TypeScript types for your extension
- ExtensionMap: Registers your extension with the library
- ExtensionStates: Defines what state information your extension provides
- ExtensionCommands: Defines what actions your extension can perform
- 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.