Migrating to v1.1
1.1 is a minor release: nothing public was removed, and code written for 1.0 keeps compiling and running. No code changes are required. It rebuilds the editor core, fixes a long list of bugs, adds a few options and methods, and brings back custom keyboards. This page lists the upgrade steps, the optional improvements, and what behaves differently.
Upgrade steps
-
Update the package (and react-native-webview, if it is older than 13.7):
yarn add @10play/tentap-editor@^1.1.0 -
Rebuild your native app. 1.1 contains a small autolinked native module (
TenTapKeyboard), used by custom keyboards. Until you rebuild, the editor works and custom keyboards use the JavaScript fallback driver.- iOS:
cd ios && pod install - Android: a new Gradle build
- Expo:
npx expo prebuild, or rebuild your dev client. Expo Go keeps working without a rebuild.
- iOS:
-
If you use the advanced setup, rebuild your editor bundle and follow Upgrading your editor-web.
- Coming from 0.x, delete the old
editorHtml.tsfrom your build folder (for exampleeditor-web/build/editorHtml.ts). Since 1.0,buildEditor.jswriteseditorHtml.jsandeditorHtml.d.tsinstead, and a Vite config withemptyOutDir: falsekeeps the old file. Metro resolves.tsbefore.js, soimport { editorHtml } from './editor-web/build/editorHtml'would keep loading the 0.x bundle.editor:buildprints a warning while such a file exists.
- Coming from 0.x, delete the old
-
Coming from 0.7.x, also follow the 1.0 migration guide. In particular, TipTap v3 renamed History to UndoRedo, so
HistoryBridgeis namedundoRedo; code that looks bridges up by'history'must use'undoRedo'. 1.1 also sends the bridge's config underhistory, so a custom editor bundle built with 0.7.x still receives it.
Requirements
- React Native 0.74 or newer (Expo SDK 51 or newer) for the native module. The Android module is built on
BaseReactPackage, which was added in 0.74, so the Android build fails on older versions. Thereact-nativepeer dependency is still*, so package managers don't check this. Stay on 1.0.x if you can't upgrade React Native. - react-native-webview 13.7 or newer. Use 13.13.3 or newer on the new architecture if the editor is inside a
ScrollView. - The Android package is still
com.tentap.TenTapViewPackage, now written in Java. The library no longer applies the Kotlin Gradle plugin, which conflicted with AGP 9's built-in Kotlin support. package.jsondeclares acodegenConfigagain (RNTenTapSpec, a native module). If a build fails on stale codegen output after upgrading, clean the build folders (ios/build,android/app/build) and rebuild.@tiptap/reactis still a dependency, so a 1.0 advanced setup that importsEditorContentfrom@tiptap/reactkeeps building. Importing it from@10play/tentap-editorinstead is recommended (Sharing tiptap).react-domis no longer installed with the package. 1.0.1 depended onreact-dom@^18.2.0, and a React 19 app then got a second, nestedreact-dom18, whichexpo-doctorreports as a duplicate (#315). The built-in editor is prebuilt with its own copy, and the native bundle never loadsreact-dom. Web apps and custom editor bundles keep areact-domthat matches theirreact, as in advanced setup. A native-only app needs nothing extra.@tiptap/reactstill listsreact-domas a peer dependency, so a native-only install may print a peer warning; that warning is safe to ignore.
Optional: the new keyboard layout
The 1.0 layout, a KeyboardAvoidingView around the Toolbar with a keyboardVerticalOffset below a header, keeps working. 1.1 adds EditorKeyboardAvoidingView, which needs no offset and also keeps the toolbar on the keyboard on edge-to-edge Android (the default in Expo SDK 53+). Swapping it in is a one-line change; see Keyboard and caret.
Custom keyboards are back
CustomKeyboard, ColorKeyboard, CustomKeyboardExtension, the colorKeyboard theme and the Color / ColorKeyboardTheme types are exported again. See Custom Keyboard Utils.
Coming from 0.7.x:
- Your code compiles unchanged.
rootRefis ignored and can be removed. - The keyboard component is now rendered in your app's own React tree. It can use your context providers and hooks, including
useBridgeState(editor)to follow the editor state. It also receiveseditor,closeandkeyboardHeightprops. - It works on the new architecture, including bridgeless mode and the React Native 0.79+ app templates.
TenTapViewis a deprecated component that renders nothing. Remove it.colorKeyboardis optional onEditorTheme, so a full theme object written for 1.0 still type-checks.editor.theme,defaultEditorThemeanddarkEditorThemeare typed with it, soeditor.theme.colorKeyboard.keyboardRootColorcompiles as in 0.7.x.- The toolbar stays visible while a custom keyboard is open, so you can drop the
hiddenlogic from the 0.7.x examples.
New options and methods
parseOptions | ProseMirror parse options, e.g. to keep whitespace |
scrollBottomOffset | extra space kept below the cursor |
avoidKeyboard | alias of avoidIosKeyboard |
mergeStyles | merge the RichText style prop instead of replacing |
rpcTimeoutMs | timeout for getHTML and the other async methods |
insertContent | insert HTML, text or JSON at the cursor |
getSelectedText | read the selected text |
setContent(content, options) | parseOptions and emitUpdate per call |
Toolbar headingItems | customize the heading toolbar; HEADING_ITEMS and ToolbarContext are exported |
TentapRpcTimeoutError, TentapUnsupportedError | errors thrown by the async methods |
useRemoteEditorBridge | subscribes to the most recently created editor |
Toolbar ListComponent | render the toolbar with another list component, such as a bottom-sheet FlatList |
linkBarTheme.hintText | placeholder of the link bar input |
useTenTap stateUpdateDebounceMs | debounce of state updates from a custom editor bundle |
Behaviour changes
These are fixes, but they change what some apps observe.
Editor identity
useEditorBridgereturns the same object on every render, so it is safe in dependency arrays; its option fields (theme,dynamicHeight, …) always read the latest render.RichTextandToolbarre-render when the options change, also under aReact.memoparent. Your own memoized components that render fromeditor.themeor another option should take that value as a prop, sinceeditoralone no longer changes.
Readiness and messaging
isReadybecomestrueas soon as the editor is created, also when it is not editable and not focused. It goes back tofalsewhile the WebView reloads.- Commands called before the editor is ready are queued and sent in order once it is ready. They used to be dropped with an "Editor isn't ready yet" warning.
- The web editor sends
editor-readyfollowed by a fullstateUpdateas soon as it is created. - If you read messages in your own
onMessage: messages can carry extra fields (editorId,v) besidestypeandpayload,editor-readyhas a payload, and there are new message types (boot-error,tentap-editor-press). Ignore what you don't use. A development warning is logged whenonMessageis passed withoutexclusivelyUseCustomOnMessage; the default is stilltrue. - If the WebView's content process is killed, the editor reloads and restores its content and settings. Edits made since the content was last read can be lost.
- On iOS, the WebView is remounted after its first load only with react-native-webview 13.12.3 and 13.12.4, which need the workaround.
useEditorContentfetches the content when it changes, not on every selection change.- Bridge configs containing quotes or
</script>no longer break the editor.
Layout
styleandcontainerStylepassed toRichTextstill replace the editor's own styles, as in 1.0, unless you set the newmergeStylesoption. The difference: withdynamicHeight, the content height is now applied after yourcontainerStyle, so your styles can no longer switch dynamic height off by accident.RichTextthrows a clear error wheneditordoesn't come fromuseEditorBridge. A spread copy such as{ ...editor }still works, as in 1.0, but its option fields are a snapshot, so prefer passingeditoritself.dynamicHeightworks in any parent, shrinks when content is deleted, keeps the scroll position when the height is capped, and no longer adds keyboard padding.
Keyboard and caret
RichTextmeasures how far the keyboard and the toolbar on it reach into the editor, and keeps the line being typed about one line above the toolbar. In 1.0 the inset was derived from the keyboard height (iOS) or a fixed toolbar height (Android), so the caret could end up under the toolbar. The document padding and the scroll threshold now come from this measurement.- This applies to every editor without
dynamicHeightwhile a keyboard is up, also withoutavoidIosKeyboard. An editor that ends above the keyboard keeps about one line of space below the caret. Until the first measurement,avoidIosKeyboardkeeps its 1.0 value. - A toolbar of your own on the keyboard that isn't marked with useKeyboardAccessory gets the default toolbar height of room.
useKeyboard()keepskeyboardHeightwhile switching between the system and a custom keyboard, and returns new fields.isKeyboardUpandkeyboardHeightbehave as in 1.0 when no custom keyboard is used.
Editing
setImageadds an empty paragraph after an image that ends the document and moves the cursor there.- Links without a scheme get
https://(www.google.com→https://www.google.com), or thedefaultProtocolpassed toLinkBridge.configureExtension. Plain email addresses getmailto:. - CSS injected with
injectCSSis re-applied when the WebView reloads.
Toolbar
shouldHideDisabledToolbarItemsalso hides disabled heading items.- The link bar no longer closes when its input loses focus. The keyboard's Done key inserts the link.
- Each toolbar context renders its own list, so the heading toolbar opens scrolled to the start.
Advanced setup
tiptapOptions.onCreate,onUpdate,onSelectionUpdateandonTransactionpassed touseTenTaprun in addition to tentap's handlers instead of replacing them. If you overrode them on purpose to stop tentap's messages, that no longer works.- Bridges and extensions are resolved once, when the editor is created.
Type-level changes
EditorBridge(withCoreBridge) has two new required members,insertContentandgetSelectedText. If you buildEditorBridgeobjects by hand, for example as test mocks, add them.setContenthas a new optional second parameter.EditorThemehas a new optionalcolorKeyboardkey.- The source types are self-contained: deep imports from
@10play/tentap-editor/src/...andmoduleResolution: "node"no longer report missing bridge methods such astoggleBold. Importing from the package root is still recommended. extendEditorInstancereceives an optional sixth argument,BridgeContext. Existing five-argument bridges are unaffected.
Deprecations
| Deprecated | Use instead |
|---|---|
CustomKeyboard rootRef prop | nothing, it's ignored |
TenTapView | nothing, it renders nothing |
CustomKeyboard onKeyboardHideAndroid prop | onClose |
Deprecated APIs keep working in 1.x. avoidIosKeyboard is not deprecated; avoidKeyboard is an alias with a clearer name.