Giter Club home page Giter Club logo

10tap-editor's People

Contributors

17amir17 avatar guyserfaty avatar ororsatti avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

10tap-editor's Issues

Dismissing the keyboard

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.

Allow setting max characters limit

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!

Dynamic css.

Would be cool if there was a way to update the css for the editor.
CoreBridge.configureCSS(customCss),

Problem of integration of ColorBridge, HighlightBridge and ImageBridge

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,
    },
})

Crash on initializaiton

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?

How can we set background color as transparent?

Screenshot 2024-05-28 at 11 22 56

I set background as image -> it works, but when I set background as transparent, editor show white background,
how can we set background color as transparent ?

  • For more information, I already set background: transparent for *, .ProseMirror, body, but it didnt work

thank you a lot

DropCursorBridge is not exported

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

how to render a sample html message using read only mode

Questions:

  • Is the way mentioned below how I'm supposed to build a sample renderer? I am unsure how to set the content using the useEditorBridge hook, I used initialContent as the suited prop. But is this how I am supposed to implement or is there something I am missing?
  • Moreover I am mapping RichTextEditor for say a list of messages, this is currently making every message scrollable individually, is there any way to stop this?

Code Sample Screenshot:

image

Output Screenshot:

image

New Arch Support

With RN .75 new arch comes out of the box, which we do not currently support

Mentions and Suggestion

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!

Advanced setup questions

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>
  );
};

Better dev command?

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

Custom Keyboard Jitter when Opened [Android]

What is expected

The custom keyboard should open smoothly like on IOS

What is happening

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.

Screen.Recording.2024-02-18.at.12.58.51.mov

Doesn't render <br> tags

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>`;

What I see in my simulator looks like this
Simulator Screenshot - iPhone 12 - 2024-05-07 at 17 34 24

Change icon tint color when active

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", }, }, }

Invariant Violation: requireNativeComponent: "TenTapView" was not found in the UIManager.

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,
    },
})

Faster Way To Inject Font

Inject the Base64 content of a font is expensive on load time, we need a better way of doing this.

Schema Format.

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.

Custom Keyboard Not Reactive

What is Expected

The custom keyboard component (any keyboard created with CustomKeyboardExtension), should be reactive and should unmount when the keyboard is closed.

What is Happening

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.

Reduce Dependencies

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

there is anyway to control link open? onLinkOpen maybe?

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?

Toolbar not display on IOS

IMG_00F92A1553F1-1

As shown in the above picture, when i start input some text, but toolbar not display as expect, I use the demo code.

Type error when using basic example and adding any bridgeExtension

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>
    );
};

Read only mode

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.

do we have onHeightChange?

do we have onHeightChange? - I mean the way to detect line break (how can I detect it's 5 lines [screenshot])
Screenshot 2024-05-23 at 14 34 42

Thankss

IOS keyboard not disappears.

Hi, im unable to close the keyboard on IOS device its working great on Android.
Also Return On Keybaord is not closing the Keyboard.

RPReplay_Final1715345403.MP4

<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>

Build failed RN 0.73.5 with New Architecture (IOS)

I'm getting this error when I try to build my app with the new architecture enabled on IOS

Screenshot 2024-03-07 at 16 41 42

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

Steps to reproduce

  1. npx react-native init newProject
  2. yarn add @10play/tentap-editor react-native-webview
  3. bundle install && cd ios && RCT_NEW_ARCH_ENABLED=1 bundle exec pod install

Libraries version

  • React Native: 0.73.5
  • Tentap: 0.4.52

Needed to add / commands in ReactNative App.

Hi,
I want to create notion like editor using tiptap in react Native
i want to implement the / commands in editor to use Commands

1_223aTv2WEZW8Tc78eY0J-A

This is in React, but i want it to be in React Native.
I'm new here, Any help will be appricated.
Thanks.

Issue with @10play/tentap-editor on Physical Android Devices

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; ```

Is there any form of web support via Expo?

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.

RichText overflow after line break

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,
    },
})

Place inside a ScrollView

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?

Add API Similar to `onChange`

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.

TypeError: _extensionLink.default.configure is not a function (it is undefined), js engine: hermes

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!

dependencies

"@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",

Minimal implementation

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

 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

Editor's initialContent support for JSON missing

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,
  })

Support for DropCursor extension?

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.