Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions example/babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ module.exports = {
},
],
['babel-plugin-inline-import', { extensions: ['.html', '.svg'] }],
'react-native-reanimated/plugin',
],
};
21 changes: 19 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,15 @@ PODS:
- React-jsi (= 0.73.5)
- React-logger (= 0.73.5)
- React-perflogger (= 0.73.5)
- RNGestureHandler (2.17.1):
- glog
- RCT-Folly (= 2022.05.16.00)
- React-Core
- RNReanimated (3.14.0):
- glog
- RCT-Folly (= 2022.05.16.00)
- React-Core
- ReactCommon/turbomodule/core
- RNScreens (3.29.0):
- glog
- RCT-Folly (= 2022.05.16.00)
Expand Down Expand Up @@ -1205,6 +1214,8 @@ DEPENDENCIES:
- React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`)
- React-utils (from `../node_modules/react-native/ReactCommon/react/utils`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNReanimated (from `../node_modules/react-native-reanimated`)
- RNScreens (from `../node_modules/react-native-screens`)
- RNSVG (from `../node_modules/react-native-svg`)
- tentap (from `../..`)
Expand Down Expand Up @@ -1326,6 +1337,10 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/react/utils"
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
RNGestureHandler:
:path: "../node_modules/react-native-gesture-handler"
RNReanimated:
:path: "../node_modules/react-native-reanimated"
RNScreens:
:path: "../node_modules/react-native-screens"
RNSVG:
Expand All @@ -1350,7 +1365,7 @@ SPEC CHECKSUMS:
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
FlipperKit: 37525a5d056ef9b93d1578e04bc3ea1de940094f
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 035f1e36e53b355cf70f6434d161b36e7d21fecd
glog: c5d68082e772fa1c511173d6b30a9de2c05a69a2
hermes-engine: 1d1835b2cc54c381909d94d1b3c8e0a2f1a94a0e
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
Expand Down Expand Up @@ -1397,6 +1412,8 @@ SPEC CHECKSUMS:
React-runtimescheduler: 814b644a5f456c7df1fba7bcd9914707152527c6
React-utils: 987a4526a2fc0acdfaf87888adfe0bf9d0452066
ReactCommon: 2947b0bffd82ea0e58ca7928881152d4c6dae9af
RNGestureHandler: 67d3f1f69d4d0c98d6e83f4229e3bbf997d1dc72
RNReanimated: f1ce27e7d23e6f941024b862ad76a7fdae93dea9
RNScreens: 17e2f657f1b09a71ec3c821368a04acbb7ebcb46
RNSVG: ba3e7232f45e34b7b47e74472386cf4e1a676d0a
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
Expand All @@ -1405,4 +1422,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 59f02bbde682eb22b765a58d4a0ce59d95964282

COCOAPODS: 1.12.0
COCOAPODS: 1.15.2
4 changes: 4 additions & 0 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
"build:ios": "cd ios && xcodebuild -workspace TenTapExample.xcworkspace -scheme TenTapExample -configuration Debug -sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO"
},
"dependencies": {
"@gorhom/bottom-sheet": "^4.6.3",
"@gorhom/portal": "^1.0.14",
"@react-navigation/native": "^6.1.9",
"@react-navigation/native-stack": "^6.9.17",
"@tiptap/extension-bubble-menu": "^2.2.1",
Expand All @@ -23,6 +25,8 @@
"@tiptap/extension-text": "^2.2.1",
"react": "18.2.0",
"react-native": "0.73.5",
"react-native-gesture-handler": "^2.17.1",
"react-native-reanimated": "^3.14.0",
"react-native-safe-area-context": "^4.8.2",
"react-native-screens": "^3.29.0",
"react-native-svg": "^14.1.0",
Expand Down
50 changes: 32 additions & 18 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { PortalProvider } from '@gorhom/portal';
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import {
createNativeStackNavigator,
type NativeStackScreenProps,
} from '@react-navigation/native-stack';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { Basic } from './Examples/Basic';
import { CustomKeyboardExample } from './Examples/CustomKeyboardExample';
import { EditorStickToKeyboardExample } from './Examples/EditorStickToKeyboardExample';
import { Advanced } from './Examples/Advanced/AdvancedRichText';
import { CustomAndStaticToolbar } from './Examples/CustomAndStaticToolbar/CustomAndStaticToolbar';
import { WithBottomSheet } from './Examples/WithBottomSheet';
import { WithKeyboard } from './Examples/WithKeyboard';
import { CustomCss } from './Examples/CustomCss';
import { ConfigureExtensions } from './Examples/ConfigureExtentions';
Expand All @@ -25,6 +28,10 @@ const examples = [
name: 'With Color Keyboard',
component: WithKeyboard,
},
{
name: 'With @gorhom/bottom-sheet',
component: WithBottomSheet,
},
{
name: 'Custom CSS',
component: CustomCss,
Expand Down Expand Up @@ -77,28 +84,35 @@ const HomeScreen = ({ navigation }: NativeStackScreenProps<any, any, any>) => {
const Stack = createNativeStackNavigator();
const App = () => {
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={({ route }) => {
return {
headerShown: route.name === 'NavigationHeader',
};
}}
>
<Stack.Screen name="Examples" component={HomeScreen} />
{examples.map((example) => (
<Stack.Screen
key={example.name}
name={example.name}
component={example.component}
/>
))}
</Stack.Navigator>
</NavigationContainer>
<GestureHandlerRootView style={homeStyles.root}>
<PortalProvider>
<NavigationContainer>
<Stack.Navigator
screenOptions={({ route }) => {
return {
headerShown: route.name === 'NavigationHeader',
};
}}
>
<Stack.Screen name="Examples" component={HomeScreen} />
{examples.map((example) => (
<Stack.Screen
key={example.name}
name={example.name}
component={example.component}
/>
))}
</Stack.Navigator>
</NavigationContainer>
</PortalProvider>
</GestureHandlerRootView>
);
};

const homeStyles = StyleSheet.create({
root: {
flex: 1,
},
container: {
flex: 1,
alignItems: 'center',
Expand Down
144 changes: 144 additions & 0 deletions example/src/Examples/WithBottomSheet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import BottomSheet, {
BottomSheetScrollView,
BottomSheetView,
} from '@gorhom/bottom-sheet';
import { Portal } from '@gorhom/portal';
import type { NativeStackScreenProps } from '@react-navigation/native-stack';
import React, { useEffect, useState } from 'react';
import {
SafeAreaView,
Platform,
StyleSheet,
Button,
Keyboard,
type KeyboardEvent,
TouchableOpacity,
Text,
KeyboardAvoidingView,
} from 'react-native';
import { RichText, Toolbar, useEditorBridge } from '@10play/tentap-editor';

const useKeyboard = () => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to import this from @10play/tentap-editor

const [keyboardHeight, setKeyboardHeight] = useState(0);

useEffect(() => {
function onKeyboardDidShow(e: KeyboardEvent) {
// Remove type here if not using TypeScript
setKeyboardHeight(e.endCoordinates.height);
}

function onKeyboardDidHide() {
setKeyboardHeight(0);
}

const showSubscription = Keyboard.addListener(
'keyboardDidShow',
onKeyboardDidShow
);
const hideSubscription = Keyboard.addListener(
'keyboardDidHide',
onKeyboardDidHide
);
return () => {
showSubscription.remove();
hideSubscription.remove();
};
}, []);

return keyboardHeight;
};

export const WithBottomSheet = ({}: NativeStackScreenProps<any, any, any>) => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am still unable to scroll on Android - seems like the scroll is getting handled by the drawer

Screen.Recording.2024-08-04.at.14.31.44.mov

const bottomSheetRef = React.useRef<BottomSheet>(null);
const keyboardHeight = useKeyboard();
const editor = useEditorBridge({
// autofocus: true,
avoidIosKeyboard: true,
initialContent,
});
const openBottomSheet = () => {
bottomSheetRef.current?.snapToIndex(0);
};

const closeBottomSheet = () => {
bottomSheetRef.current?.close();
};

return (
<SafeAreaView style={exampleStyles.fullScreen}>
<Button title="Open Bottom Sheet" onPress={openBottomSheet} />
<Portal>
<BottomSheet
snapPoints={['90%']}
ref={bottomSheetRef}
keyboardBehavior="extend"
android_keyboardInputMode="adjustResize"
keyboardBlurBehavior="restore"
bottomInset={0.2}
>
<BottomSheetScrollView
keyboardDismissMode="interactive"
keyboardShouldPersistTaps="handled"
>
<BottomSheetView>
<TouchableOpacity
onPress={closeBottomSheet}
style={exampleStyles.closeButton}
>
<Text style={exampleStyles.closeButtonText}>
Close BottomSheet
</Text>
</TouchableOpacity>
</BottomSheetView>
<BottomSheetView style={exampleStyles.editorContainer}>
<RichText editor={editor} hideKeyboardAccessoryView={false} />
</BottomSheetView>
</BottomSheetScrollView>
<Portal>
<KeyboardAvoidingView
style={{
position: 'absolute',
bottom: Keyboard.isVisible()
? Platform.OS === 'android'
? 0
: keyboardHeight
: -100,
width: '100%',
}}
>
<Toolbar editor={editor} />
</KeyboardAvoidingView>
</Portal>
</BottomSheet>
</Portal>
</SafeAreaView>
);
};

const exampleStyles = StyleSheet.create({
closeButton: {
marginTop: 16,
marginHorizontal: 16,
paddingHorizontal: 16,
paddingVertical: 8,
borderWidth: 2,
borderRadius: 8,
},
closeButtonText: {
textAlign: 'center',
},
editorContainer: {
height: 100,
marginHorizontal: 16,
paddingHorizontal: 16,
marginTop: 10,
borderWidth: 1,
},
fullScreen: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});

const initialContent = `<p>This is a basic example!</p>`;
5 changes: 4 additions & 1 deletion src/RichText/Toolbar/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
StyleSheet,
Platform,
View,
type FlatListProps,
} from 'react-native';
import { useBridgeState } from '../useBridgeState';
import React from 'react';
Expand All @@ -21,6 +22,7 @@ interface ToolbarProps {
editor: EditorBridge;
hidden?: boolean;
items?: ToolbarItem[];
ListComponent?: React.ComponentType<FlatListProps<any>>;
}

export const toolbarStyles = StyleSheet.create({});
Expand All @@ -35,6 +37,7 @@ export function Toolbar({
editor,
hidden = undefined,
items = DEFAULT_TOOLBAR_ITEMS,
ListComponent = FlatList,
}: ToolbarProps) {
const editorState = useBridgeState(editor);
const { isKeyboardUp } = useKeyboard();
Expand All @@ -56,7 +59,7 @@ export function Toolbar({
case ToolbarContext.Main:
case ToolbarContext.Heading:
return (
<FlatList
<ListComponent
data={toolbarContext === ToolbarContext.Main ? items : HEADING_ITEMS}
style={[
editor.theme.toolbar.toolbarBody,
Expand Down
11 changes: 6 additions & 5 deletions website/docs/api/Components.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@ A react component of a basic Toolbar that include these features:

props:

| name | type | default | description |
| ------ | --------------- | --------------------- | ----------------------------------------------------------------------- |
| editor | `EditorBridge` | | The bridge instance that created with [useEditorBridge](./EditorBridge) |
| hidden | `boolean` | | a prop to control if toolbar shown |
| items | `ToolbarItem[]` | DEFAULT_TOOLBAR_ITEMS | array of ToolbarItem's that will be shown on the toolbar |
| name | type | default | description |
|---------------| --------------- |-----------------------|-------------------------------------------------------------------------------------------|
| editor | `EditorBridge` | | The bridge instance that created with [useEditorBridge](./EditorBridge) |
| hidden | `boolean` | | a prop to control if toolbar shown |
| items | `ToolbarItem[]` | DEFAULT_TOOLBAR_ITEMS | array of ToolbarItem's that will be shown on the toolbar |
| ListComponent | `React.ComponentType<FlatListProps<any>>` | FlatList | <b>Optional</b> prop to use custom Flatlist implementation as container for Toolbar Items |

See how we add a custom toolbar item in the [color keyboard example](../examples/colorKeyboard.md)

Expand Down
Loading