10play / 10tap-editor Goto Github PK
View Code? Open in Web Editor NEWReact Native Rich Text Editor
License: MIT License
React Native Rich Text Editor
License: MIT License
I'm trying to add Table into 10tap-editor. Please help
I was having issues dismissing the keyboard, managed to solve it.
Just for future reference, use the editor.blur()
function cause calling Keyboard.dismiss()
wont do it. We need to communicate the change to the webview, which the blur fn does.
Below is the crash log
crash_log_ios.txt
When you try to replace color keyboard colors, the default colors still get added
There is current no easy way to inject custom html into the editor.
Hello, is there a way to set a maximum character limit for the RichText component? I couldn’t find any information in the documentation, nor could I find details on making the element controlled to implement my own logic.
Thanks!
Would be cool if there was a way to update the css for the editor.
CoreBridge.configureCSS(customCss),
I'd like to know why I don't have the tools to add an image with the ImageBridge, a color to my text with the ColorBridge and a colored background with the HIghlightBridge. Here's my code.
Does anyone know where this is coming from? That's my dependencies :
"@10play/tentap-editor@^0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@10play/tentap-editor/-/tentap-editor-0.5.0.tgz#c8be670c3dd702620d126e99210a3e8869da5cc5"
integrity sha512-TaIfUPO6gcFF1ID4pb2on6IUpWLDb5iXUCt3hNRXQz/sHpxuaTfuCFWTc2uW5n3QMeFAPmGEH7ZMdxEGT4SlqA==
dependencies:
"@tiptap/extension-blockquote" "^2.2.1"
"@tiptap/extension-bold" "^2.2.1"
"@tiptap/extension-bullet-list" "^2.2.1"
"@tiptap/extension-code" "^2.2.1"
"@tiptap/extension-code-block" "^2.2.1"
"@tiptap/extension-color" "^2.1.16"
"@tiptap/extension-document" "^2.2.1"
"@tiptap/extension-dropcursor" "^2.2.4"
"@tiptap/extension-hard-break" "^2.3.1"
"@tiptap/extension-heading" "^2.2.1"
"@tiptap/extension-highlight" "^2.1.16"
"@tiptap/extension-history" "^2.2.1"
"@tiptap/extension-horizontal-rule" "^2.2.1"
"@tiptap/extension-image" "^2.2.1"
"@tiptap/extension-italic" "^2.2.1"
"@tiptap/extension-link" "^2.1.16"
"@tiptap/extension-list-item" "^2.2.1"
"@tiptap/extension-ordered-list" "^2.2.1"
"@tiptap/extension-placeholder" "^2.2.1"
"@tiptap/extension-strike" "^2.2.1"
"@tiptap/extension-task-item" "^2.1.16"
"@tiptap/extension-task-list" "^2.1.16"
"@tiptap/extension-text-style" "^2.1.16"
"@tiptap/extension-underline" "^2.1.16"
"@tiptap/pm" "^2.1.16"
"@tiptap/react" "^2.1.16"
"@tiptap/starter-kit" "^2.1.16"
lodash "^4.17.21"
react-dom "^18.2.0"
import { SafeAreaView, KeyboardAvoidingView, Platform, StyleSheet, View } from 'react-native';
import { useEditorBridge, RichText, Toolbar, PlaceholderBridge, useEditorContent, CoreBridge, TenTapStartKit, ColorBridge, HighlightBridge, ImageBridge } from '@10play/tentap-editor';
import { useEffect } from 'react';
import FigtreeRegular64 from "@/assets/fonts/figtree/Figtree-Regular_base64"
import { SIZE } from '@/assets/themes/theme';
const Wysiwyg = ({
displayToolbar,
placeholder,
onChange,
onEditorReady
}) => {
const customFont = `
@font-face {
font-family: 'Figtree';
src: url('${FigtreeRegular64}');
font-weight: normal;
font-style: normal;
font-display: swap;
}
* {
font-family: 'Figtree';
word-break: break-word
}
`
const editor = useEditorBridge({
bridgeExtensions: [
...TenTapStartKit,
PlaceholderBridge.configureExtension({
placeholder: placeholder,
}),
CoreBridge.configureCSS(customFont)
],
})
const content = useEditorContent(editor, { type: 'html' })
useEffect(() => {
onChange(content)
}, [content])
useEffect(() => {
onEditorReady(editor)
}, [editor])
return (
<SafeAreaView style={{ flex: 1, paddingHorizontal: SIZE.padding }}>
<RichText editor={editor} />
{displayToolbar && (
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.keyboardAvoidingView}
>
<Toolbar editor={editor} />
</KeyboardAvoidingView>
)}
</SafeAreaView>
)
}
export default Wysiwyg
const styles = StyleSheet.create({
keyboardAvoidingView: {
position: 'absolute',
width: '100%',
bottom: 0,
},
})
This library has crash on useEditorBridge hook this line const webviewRef = useRef<WebView>(null);
.
Sometimes this ref is null and it is not going to work every time.
We are having trouble with this because most of the time it won't work.
We are using "react-native": "0.73.2" version.
Any solutions?
Hey there! tried open a small PR for this but don't have write access.
As the title says, the DropCursor bridge is there and all but is not exported on src/index.tsx
. Super small fix
With RN .75 new arch comes out of the box, which we do not currently support
Hey there, I'm just starting to use 10tap on a project and I was wondering if there's any compatibility with the suggestions and mentions plugin from tiptap. This is a must-have for me.
If this feature does not exist yet, I would be happy to make a contribution if you could share some general steps that I could follow to implement this.
Thanks in advance!
Hello! First of all, thank you so much for making such a nice rich text library available for react native 👍
I'm applying the advanced setup to implement 'readonly mode / multiple placeholder' and I'm not quite sure how the advanced setup implements its own bridgeExtension.
For example, if I implemented a custom bridgeExtension called PlaceholderWithTitleBridge, would this need to be added to both advancedEditor (Web: useTenTap-bridges) and advancedRichText (RN: useEditorBridge-bridgeExtensions)? I'm trying to understand the examples and documentation + source code on GitHub, but I'm not sure due to my lack of knowledge
And I'm using i18next's useTranslation hook for internalization support. With the useTranslation hook, I get 2 placeholder values (title, content) from the translate file. I functionized PlaceholderWithTitleBridge to use them in PlaceholderWithTitleBridge. However, this way there seems to be no way to pass the placeholder values from advancedEditor(web). This seems to be wrong.
Can anyone help me with this gap in my knowledge? If there is a clear path, I'd love to know.
I've attached the source code for comment. thank you!
// PlaceholderWithTitleBridge.ts (Custom BridgeExtension)
import Placeholder from "@tiptap/extension-placeholder";
import { BridgeExtension } from "@10play/tentap-editor";
type PlaceholderEditorWithTitleState = {};
type PlaceholderEditorWithTitleInstance = {};
declare module "@10play/tentap-editor" {
interface BridgeState extends PlaceholderEditorWithTitleState {}
interface EditorBridge extends PlaceholderEditorWithTitleInstance {}
}
export const PlaceholderWithTitleBridge = ({
titlePlaceholder,
contentPlaceholder,
}: {
titlePlaceholder: string | undefined;
contentPlaceholder: string | undefined;
}) =>
new BridgeExtension<
PlaceholderEditorWithTitleState,
PlaceholderEditorWithTitleInstance
>({
tiptapExtension: Placeholder.configure({
showOnlyCurrent: false,
placeholder: ({ node }) => {
if (node.type.name === "title") {
return titlePlaceholder ?? ''; // need to fix
} else {
return contentPlaceholder ?? ''; // need to fix
}
},
}),
extendCSS: `
h1.is-empty:nth-child(1)::before,
p.is-empty:nth-child(2):last-child::before {
color: #adb5bd;
content: attr(data-placeholder);
float: left;
height: 0;
pointer-events: none;
}
`,
});
// AdvancedRichText.tsx (in RN component)
export default function AdvancedRichText() {
const { t } = useTranslation(); // i18next
const editor = useEditorBridge({
customSource: editorHtml,
bridgeExtensions: [
CoreBridge,
ListItemBridge,
BulletListBridge,
OrderedListBridge,
TaskListBridge,
PlaceholderWithTitleBridge({ titlePlaceholder: t("Editor:title_placeholder"), contentPlaceholder: t("Editor:content_placeholder") }),
],
avoidIosKeyboard: true,
});
const content = useEditorContent(editor, { type: "json" });
useEffect(() => {
setTimeout(() => {
editor.focus("start");
}, 200); // autofocus:true not working
}, []);
useEffect(() => {
StatusBar.setBarStyle("light-content"); // need to fix
}, [content]);
return (
<BottomSheetModalProvider>
<StatusBar barStyle={"light-content"} hidden={false} />
<Container>
<RichText editor={editor} />
</Container>
</BottomSheetModalProvider>
);
}
// AdvancedEditor.tsx (in editor-web)
const DocumentWithTitle = Document.extend({
content: "title block*",
});
const Title = Heading.extend({
name: "title",
group: "title",
parseHTML: () => [{ tag: "h1:first-child" }],
}).configure({ levels: [1] });
export const AdvancedEditor = () => {
const editor = useTenTap({
bridges: [
CoreBridge,
ListItemBridge,
BulletListBridge,
OrderedListBridge,
TaskListBridge,
// PlaceholderWithTitleBridge({
// titlePlaceholder: ??,
// contentPlaceholder: ??,
// }),
],
tiptapOptions: {
extensions: [DocumentWithTitle, Paragraph, Text, Title],
},
});
return (
<div style={{ backgroundColor: #FFF }}>
<EditorContent editor={editor} />
</div>
);
};
I use advanced mode as of now and I've been having some issues. Since what I see on dev mode is only half of what will get rendered on RN I don't see much value developing the editor on localhost with a Vite dev server.
That's why i've changed yarn editor:dev
to be vite --config ./editor-web/vite.config.mts -w build
. This will not run the vite dev server on port 3000 but instead will rebuild the single file html every time there's a change on the watched files.
The next problem then is that we need to run the post-build command for 10tap to build the custom editor. For this, I added the following custom plugin to my vite.config.ts
plugins: [
react(),
viteSingleFile(),
{
name: 'postbuild-commands', // the name of your custom plugin. Could be anything.
closeBundle: async () => {
exec('npm run editor:post-build', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
});
},
},
],
And voilá! If i change the advanced editor source I immediately see the change on RN side.
The only bad thing is that I do see a small flash of a Metro error. It seems Vite deleted the build folder when starting a new build. I tried setting build.emptyOutDir: false
on my vite config but it didn't work. So far it's not that big of an issue, can probably be solved with some investigation.
Let me know what you think
The custom keyboard should open smoothly like on IOS
When opening the CustomKeyboard on Android the soft keyboard is hidden and the softInputMode
on the window is changes, this causes a jitter for a frame when opening the custom keyboard.
I've been using the Basic example of using the editor but it doesn't seem to respect <br>
tags.
To test, I create a new expo project, then replace the HomeScreen component with this
import type { NativeStackScreenProps } from '@react-navigation/native-stack';
import React from 'react';
import {
SafeAreaView,
KeyboardAvoidingView,
Platform,
StyleSheet,
} from 'react-native';
import { RichText, Toolbar, useEditorBridge } from '@10play/tentap-editor';
export default function HomeScreen() {
const editor = useEditorBridge({
autofocus: true,
avoidIosKeyboard: true,
initialContent,
});
return (
<SafeAreaView style={exampleStyles.fullScreen}>
<RichText editor={editor} />
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={exampleStyles.keyboardAvoidingView}
>
<Toolbar editor={editor} />
</KeyboardAvoidingView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
titleContainer: {
flexDirection: 'row',
alignItems: 'center',
gap: 8,
},
stepContainer: {
gap: 8,
marginBottom: 8,
},
reactLogo: {
height: 178,
width: 290,
bottom: 0,
left: 0,
position: 'absolute',
},
});
const exampleStyles = StyleSheet.create({
fullScreen: {
flex: 1,
},
keyboardAvoidingView: {
position: 'absolute',
width: '100%',
bottom: 0,
},
});
const initialContent = `<p>This <br/><br/>is a <br/><strong>basic example!</strong></p>`;
Is it possible to change the color of the toolbar icon when it's active? I tried with this code below but it didn't work.
theme: { toolbar: { icon: { tintColor: "#bafcca", }, iconActive: { tintColor: "#43bc32", }, }, }
I have this error : Invariant Violation: requireNativeComponent: "TenTapView" was not found in the UIManager.
import PenIcon from "@/assets/icons/PenIcon";
import { useKeyboard, useBridgeState, Toolbar, ColorKeyboard } from "@10play/tentap-editor";
const ToolbarWithColor = ({
editor,
activeKeyboard,
setActiveKeyboard
}) => {
// Get updates of editor state
const editorState = useBridgeState(editor);
const { isKeyboardUp: isNativeKeyboardUp } = useKeyboard();
const customKeyboardOpen = activeKeyboard !== undefined;
const isKeyboardUp = isNativeKeyboardUp || customKeyboardOpen;
// Here we make sure not to hide the keyboard if our custom keyboard is visible
const hideToolbar =
!isKeyboardUp || (!editorState.isFocused && !customKeyboardOpen);
return (
<Toolbar
editor={editor}
hidden={hideToolbar}
items={[
{
onPress: () => () => {
const isActive = activeKeyboard == ColorKeyboard.id;
if (isActive) editor.focus();
setActiveKeyboard(isActive ? undefined : ColorKeyboard.id);
},
active: () => activeKeyboard === ColorKeyboard.id,
disabled: () => false,
image: () => PenIcon,
},
]}
/>
)
}
export default ToolbarWithColor
import { SafeAreaView, KeyboardAvoidingView, Platform, StyleSheet, View } from 'react-native';
import { useEditorBridge, RichText, PlaceholderBridge, useEditorContent, CoreBridge, TenTapStartKit, ColorBridge, HighlightBridge, ImageBridge, CustomKeyboard } from '@10play/tentap-editor';
import { useEffect, useRef, useState } from 'react';
import FigtreeRegular64 from "@/assets/fonts/figtree/Figtree-Regular_base64"
import { SIZE } from '@/assets/themes/theme';
import ToolbarWithColor from './ToolbarWithColor';
const Wysiwyg = ({
displayToolbar,
placeholder,
onChange,
onEditorReady
}) => {
const customFont = `
@font-face {
font-family: 'Figtree';
src: url('${FigtreeRegular64}');
font-weight: normal;
font-style: normal;
font-display: swap;
}
* {
font-family: 'Figtree';
word-break: break-word;
}
`
const rootRef = useRef(null)
const [activeKeyboard, setActiveKeyboard] = useState()
const editor = useEditorBridge({
avoidIosKeyboard: true,
bridgeExtensions: [
...TenTapStartKit,
PlaceholderBridge.configureExtension({
placeholder: placeholder,
}),
CoreBridge.configureCSS(customFont),
ColorBridge.configureExtension({
types: ['textStyle'],
}),
HighlightBridge,
ImageBridge.configureExtension({
inline: true,
})
],
})
const content = useEditorContent(editor, { type: 'html' })
useEffect(() => {
onChange(content)
}, [content])
useEffect(() => {
onEditorReady(editor)
}, [editor])
return (
<SafeAreaView style={{ flex: 1 }} ref={rootRef}>
<View style={{ flex: 1, paddingHorizontal: SIZE.padding }}>
<RichText editor={editor} />
</View>
{displayToolbar && (
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.keyboardAvoidingView}
>
<ToolbarWithColor
editor={editor}
activeKeyboard={activeKeyboard}
setActiveKeyboard={setActiveKeyboard}
ColorKeyboard={ColorKeyboard}
/>
<CustomKeyboard
rootRef={rootRef}
activeKeyboardID={activeKeyboard}
setActiveKeyboardID={setActiveKeyboard}
keyboards={[ColorKeyboard]}
editor={editor}
/>
</KeyboardAvoidingView>
)}
</SafeAreaView>
)
}
export default Wysiwyg
const styles = StyleSheet.create({
keyboardAvoidingView: {
position: 'absolute',
width: '100%',
bottom: 0,
},
})
Inject the Base64 content of a font is expensive on load time, we need a better way of doing this.
Hi, i have a editor Slate.js
running in production, it gives me only output as JSON.
And 10Tap accepts json but both of them have different json schema .
Is there a way to customize the JSON Schema format according my needs.
The custom keyboard component (any keyboard created with CustomKeyboardExtension
), should be reactive and should unmount when the keyboard is closed.
Currently we get reactive data in the custom keyboard from the useRemoteEditorBridge
hook which basically listens for changes on the editor and stops listening when unmounted. When the the keyboard is closed the keyboard's root view is removed from the view on the native side, but is not unmounted on the react side. So all of the JS is still alive there and it still listens for changes on the editor.
Currently tiptap and all of it's extension are deps, but I might not have to be this way since it is bundled anyways into a ts file. It is however imported inside each bridge, which might cause problems
On the editor I was able to add a link but was not able to open an link inside the editor, when click on the link, the editor controls of course take preference, so when click on it just select the work that contains the link, there is any way to open the link? and is yes, there is any way to control this action?
Versions:
"@10play/tentap-editor": "^0.4.55",
"expo": "~50.0.14",
I'm using the iOS simulator with expo go, but I also tried eas build and running it on the dev client and I got the same error.
I just have just made a simple expo project and used nothing but the example code for 10tap in the docs. It works fine but when I add the bridgeExtensions field, I get this error:
ERROR TypeError: editor.updateScrollThresholdAndMargin is not a function (it is undefined)
This error is located at:
in RichText (at App.js:24)
in RCTSafeAreaView (at App.js:23)
in Basic (at withDevTools.ios.js:25)
in withDevTools(Basic) (at renderApplication.js:57)
in RCTView (at View.js:116)
in View (at AppContainer.js:127)
in RCTView (at View.js:116)
in View (at AppContainer.js:155)
in AppContainer (at renderApplication.js:50)
in main(RootComponent) (at renderApplication.js:67), js engine: hermes
Interestingly when I make it "avoidIosKeyboard: false" then the error disappears but the editor doesn't work.
Here's my code:
import React, { useEffect } from "react";
import {
SafeAreaView,
View,
KeyboardAvoidingView,
Platform,
StyleSheet,
} from "react-native";
import {
LinkBridge,
RichText,
Toolbar,
useEditorBridge,
} from "@10play/tentap-editor";
export const Basic = () => {
const editor = useEditorBridge({
autofocus: true,
avoidIosKeyboard: true,
bridgeExtensions: [LinkBridge.configureExtension({ openOnClick: false })],
initialContent: initialContent,
});
return (
<SafeAreaView style={exampleStyles.fullScreen}>
<RichText editor={editor} />
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={exampleStyles.keyboardAvoidingView}
>
<Toolbar editor={editor} />
</KeyboardAvoidingView>
</SafeAreaView>
);
};
Hey! I'd like to implement a bridge (or add options to an existing one) to be able to turn on/off the readonly mode of the editor. Is this something you have a preference on how to implement?
Right now I am currently rendering the html on a webview with all my css manually copied in it. So it'd be cool to hand a prop on the react native side to the editor to enable/disable it.
Hi, im unable to close the keyboard on IOS device its working great on Android.
Also Return On Keybaord is not closing the Keyboard.
<SafeAreaView style={styles.fullScreen}> <RichText startInLoadingState={true} onLoad={() => { const json = convertSchemaToJSON(params.content); editor.setContent(JSON.parse(json)); }} editor={editor} /> <KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : "height"} style={styles.keyboardAvoidingView} > <Toolbar editor={editor} /> </KeyboardAvoidingView> </SafeAreaView>
I'm getting this error when I try to build my app with the new architecture enabled on IOS
My podfile:
# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
'require.resolve(
"react-native/scripts/react_native_pods.rb",
{paths: [process.argv[1]]},
)', __dir__]).strip
platform :ios, min_ios_version_supported
prepare_react_native_project!
# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set.
# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded
#
# To fix this you can also exclude `react-native-flipper` using a `react-native.config.js`
# ```js
# module.exports = {
# dependencies: {
# ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}),
# ```
flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled
linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
use_frameworks! :linkage => linkage.to_sym
end
target 'pellRichWithWebView' do
config = use_native_modules!
use_react_native!(
:path => config[:reactNativePath],
# Enables Flipper.
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
# you should disable the next line.
:flipper_configuration => flipper_config,
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/.."
)
target 'pellRichWithWebViewTests' do
inherit! :complete
# Pods for testing
end
post_install do |installer|
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false
)
end
end
npx react-native init newProject
yarn add @10play/tentap-editor react-native-webview
bundle install && cd ios && RCT_NEW_ARCH_ENABLED=1 bundle exec pod install
Hi,
I want to create notion like editor using tiptap in react Native
i want to implement the / commands in editor to use Commands
This is in React, but i want it to be in React Native.
I'm new here, Any help will be appricated.
Thanks.
I am encountering an issue with the "@10play/tentap-editor" package when running my React Native application on physical Android device. Despite functioning correctly on Android emulators, the text editor component fails to display on physical Android phone.
Upon investigation, I discovered that certain aspects of my code appear to be functioning only on Android emulator, However, before making any changes to my code, I wanted to reach out and inquire if there's something iam missing of the "@10play/tentap-editor" package im not aware of.. of any known issues or compatibility limitations specific to Android devices.
I have thoroughly tested the application on multiple physical Android devices to ensure that the issue is not device-specific. Despite these efforts, the problem persists across different models of Android phones.
Below is the relevant section of my code for reference:
import { SafeAreaView, KeyboardAvoidingView, Platform, TouchableOpacity, StyleSheet } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
import { useNavigation } from '@react-navigation/native';
import { RichText, Toolbar, useEditorBridge } from '@10play/tentap-editor';
const AddToDoScreen = ({ route }) => {
const [text, setText] = useState('');
const { todo } = route.params || {};
const navigation = useNavigation();
// Initialize the 10tap editor
const editor = useEditorBridge({
autofocus: true,
avoidIosKeyboard: true,
initialContent: todo ? todo.text : '',
});
//console.log('Editor initialized:', editor);
useEffect(() => {
if (todo) {
// Set initial content of the editor to the text of the todo
console.log("Todo Text:", todo.text);
editor.setContent(todo.text);
}
}, [todo]);
const addTodo = () => {
editor.getText().then((content) => {
if (content.trim() !== '') {
if (todo) {
const updatedTodo = { ...todo, text: content };
navigation.navigate('TodoScreen', { newTodo: updatedTodo });
} else {
const newTodo = { id: Date.now().toString(), text: content, createdAt: new Date().toISOString() };
navigation.navigate('TodoScreen', { newTodo});
}
setText('');
}
});
};
return (
<SafeAreaView style={styles.fullScreen}>
<RichText editor={editor} />
<KeyboardAvoidingView
behavior={Platform.OS === 'android' ? 'padding' : 'height'}
style={styles.keyboardAvoidingView}
>
<Toolbar editor={editor} />
</KeyboardAvoidingView>
<TouchableOpacity style={styles.addButton} onPress={addTodo}>
<Icon name="plus" size={20} color="white" />
</TouchableOpacity>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
fullScreen: {
flex: 1,
},
keyboardAvoidingView: {
position: 'absolute',
width: '100%',
bottom: 0,
},
addButton: {
position: 'absolute',
bottom: 20,
right: 20,
backgroundColor: 'blue',
width: 40,
height: 40,
borderRadius: 20,
justifyContent: 'center',
alignItems: 'center',
},
});
export default AddToDoScreen; ```
Really enjoying the iOS and Android experience! But I have a bare react native app that uses Expo to also ship a web version of the app. Would I be able to utilize this library for that use case? It doesn't seem so with the two platform iOS and Android specific code but wanted to see if it is possible.
Hello, I have a problem when my RichText takes up a large part of my screen, when I have no content inside I can scroll inside. When I add content and skip a line, the first line is hidden at the top and I have to scroll to see it. How can I fix this?
Basically, the question is: how can I modify the css of my RichText container?
import { SafeAreaView, KeyboardAvoidingView, Platform, StyleSheet, View } from 'react-native';
import { useEditorBridge, RichText, Toolbar, PlaceholderBridge, useEditorContent, CoreBridge, TenTapStartKit, ColorBridge, HighlightBridge, ImageBridge } from '@10play/tentap-editor';
import { useEffect } from 'react';
import FigtreeRegular64 from "@/assets/fonts/figtree/Figtree-Regular_base64"
import { SIZE } from '@/assets/themes/theme';
const Wysiwyg = ({
displayToolbar,
placeholder,
onChange,
onEditorReady
}) => {
const customFont = `
@font-face {
font-family: 'Figtree';
src: url('${FigtreeRegular64}');
font-weight: normal;
font-style: normal;
font-display: swap;
}
* {
font-family: 'Figtree';
word-break: break-word;
}
`
const editor = useEditorBridge({
avoidIosKeyboard: true,
bridgeExtensions: [
...TenTapStartKit,
PlaceholderBridge.configureExtension({
placeholder: placeholder,
}),
CoreBridge.configureCSS(customFont),
ColorBridge.configureExtension({
types: ['textStyle'],
}),
HighlightBridge,
ImageBridge.configureExtension({
inline: true,
})
],
})
const content = useEditorContent(editor, { type: 'html' })
useEffect(() => {
onChange(content)
}, [content])
useEffect(() => {
onEditorReady(editor)
}, [editor])
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1, paddingHorizontal: SIZE.padding }}>
<RichText editor={editor} style={{ overflow: 'hidden' }} />
</View>
{displayToolbar && (
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.keyboardAvoidingView}
>
<Toolbar editor={editor} />
</KeyboardAvoidingView>
)}
</SafeAreaView>
)
}
export default Wysiwyg;
const styles = StyleSheet.create({
keyboardAvoidingView: {
position: 'absolute',
width: '100%',
bottom: 0,
},
})
In the CustomAndStaticToolbar example there's a component above the RTE, but when the content from the RTE does not fit on the screen, the top view remains static.
What's the best approach for have the top component & RTE scroll together?
Currently there is no easy way to get changed content when it is changed. This is on purpose because sending the doc's content each change with messages between the webview and native part can be expensive.
We should expose some api to make this performant.
Expose tiptap schema on CoreBridge
When trying to check the operation with a minimal implementation, a TypeError is output and cannot be checked.
I was struggling with the implementation of the editor and would love to use this library.
Thank you for your contribution to React Native!
"@10play/tentap-editor": "^0.5.0",
"expo": "~50.0.17",
"react-native": "0.73.6",
"react-native-web": "~0.19.10",
"react-native-webview": "13.6.4",
import React from 'react';
import { KeyboardAvoidingView, Platform, StyleSheet } from 'react-native';
import { RichText, Toolbar, useEditorBridge } from '@10play/tentap-editor';
import { AppView } from '@/components/Themed';
export const ExampleScreen = () => {
const editor = useEditorBridge();
return (
<AppView style={exampleStyles.fullScreen}>
<RichText editor={editor} />
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={exampleStyles.keyboardAvoidingView}
>
<Toolbar editor={editor} />
</KeyboardAvoidingView>
</AppView>
);
};
const exampleStyles = StyleSheet.create({
fullScreen: {
flex: 1,
},
keyboardAvoidingView: {
position: 'absolute',
width: '100%',
bottom: 0,
},
});
ERROR TypeError: _extensionLink.default.configure is not a function (it is undefined), js engine: hermes
ERROR Invariant Violation: "main" has not been registered. This can happen if:
* Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project.
* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called., js engine: hermes
I noticed that initialContent can't accept JSON when tiptap editor does. I have a simple change that should work and we tested it too. With this change we should be able to use the code below:
const editor = useEditorBridge({
autofocus: true,
avoidIosKeyboard: true,
initialContent: {
type: "doc",
content: [
{
type: "paragraph",
content: [
{
type: "text",
text: "Leave a note ",
},
{
type: "text",
marks: [
{
type: "bold",
},
],
text: "—text in bold",
},
],
},
],
},
// bridgeExtensions: [...TenTapStartKit, CodeBridge.configureCSS(editorCustomCSS)],
// theme: customTheme,
})
First off, this library seems amazing. I've struggled in the past with RN WYSIWYGs, so thank you for your work in bringing a dedicated & robust experience to the framework.
I'm working on a new app, and 10tap seems very promising after only playing with it for 10 minutes. The TaskList support is a deal-maker for us!
Do you plan to add support for the DropCursor extension? That would help a lot in making this thing feel like Notion et al.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.