diff --git a/.gitignore b/.gitignore index 33b3e14..b03dd78 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ jsconfig.json # build/ !src/editor/build +!example/src/Examples/Advanced/Editor/build *.pbxuser !default.pbxuser *.mode1v3 diff --git a/example/package.json b/example/package.json index e168122..df6549a 100644 --- a/example/package.json +++ b/example/package.json @@ -5,6 +5,8 @@ "scripts": { "android": "react-native run-android && yarn reverse-android", "reverse-android": "adb reverse tcp:3000 tcp:3000", + "editor:dev": "vite --config ./src/Examples/Advanced/Editor/vite.config.ts", + "editor:build": "vite --config ./src/Examples/Advanced/Editor/vite.config.ts build", "ios": "react-native run-ios", "start": "react-native start", "build:android": "cd android && ./gradlew assembleDebug --no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a", @@ -26,9 +28,12 @@ "@react-native/babel-preset": "0.73.19", "@react-native/metro-config": "0.73.3", "@react-native/typescript-config": "0.73.1", + "@tiptap/pm": "^2.2.1", + "@tiptap/react": "^2.2.1", "babel-plugin-inline-import": "^3.0.0", "babel-plugin-module-resolver": "^5.0.0", - "pod-install": "^0.1.0" + "pod-install": "^0.1.0", + "vite": "^5.0.12" }, "engines": { "node": ">=18" diff --git a/example/src/App.tsx b/example/src/App.tsx index bc01a33..8d9663b 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -8,6 +8,7 @@ import { import { Basic } from './Examples/Basic'; import { CustomKeyboardExample } from './Examples/CustomKeyboardExample'; import { EditorStickToKeyboardExample } from './Examples/EditorStickToKeyboardExample'; +import { Advanced } from './Examples/Advanced/AdvancedRichText'; const examples = [ { @@ -22,6 +23,10 @@ const examples = [ name: 'EditorStickToKeyboardExample', component: EditorStickToKeyboardExample, }, + { + name: 'Advanced', + component: Advanced, + }, ]; const HomeScreen = ({ navigation }: NativeStackScreenProps) => { diff --git a/example/src/Examples/Advanced/AdvancedRichText.tsx b/example/src/Examples/Advanced/AdvancedRichText.tsx new file mode 100644 index 0000000..f06c38d --- /dev/null +++ b/example/src/Examples/Advanced/AdvancedRichText.tsx @@ -0,0 +1,85 @@ +import type { NativeStackScreenProps } from '@react-navigation/native-stack'; +import React, { useRef } from 'react'; +import { + SafeAreaView, + View, + KeyboardAvoidingView, + Platform, + StyleSheet, +} from 'react-native'; +import { + ColorBridge, + HighlightBridge, + ImageBridge, + LinkBridge, + RichText, + TaskListBridge, + TenTapStartKit, + Toolbar, + UnderlineBridge, + useEditor, +} from 'tentap'; + +// @ts-ignore +import AdvancedEditor from './Editor/build/index.html'; +import { CustomKeyboard } from '../../../../src/RichText/Keyboard'; +import { ColorKeyboard } from '../../../../src/RichText/Keyboard/ColorKeyboard'; + +const exampleStyles = StyleSheet.create({ + fullScreen: { + flex: 1, + }, + keyboardAvoidingView: { + position: 'absolute', + width: '100%', + bottom: 0, + }, +}); + +export const Advanced = ({}: NativeStackScreenProps) => { + const editor = useEditor({ + initialContent: `

This is a basic example of implementing images.

s

`, + plugins: [ + TenTapStartKit, + UnderlineBridge, + ImageBridge, + TaskListBridge, + LinkBridge, + ColorBridge, + HighlightBridge, + ], + }); + const TapRef = useRef(null); + const [activeKeyboard, setActiveKeyboard] = React.useState(); + + return ( + + + + + + + + ); +}; diff --git a/example/src/Examples/Advanced/Editor/AdvancedEditor.tsx b/example/src/Examples/Advanced/Editor/AdvancedEditor.tsx new file mode 100644 index 0000000..2617465 --- /dev/null +++ b/example/src/Examples/Advanced/Editor/AdvancedEditor.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import { EditorContent } from '@tiptap/react'; +import { useTenTap } from 'tentap'; + +export const AdvancedEditor = () => { + const editor = useTenTap(); + + return ; +}; diff --git a/example/src/Examples/Advanced/Editor/build/index.html b/example/src/Examples/Advanced/Editor/build/index.html new file mode 100644 index 0000000..0d61ad6 --- /dev/null +++ b/example/src/Examples/Advanced/Editor/build/index.html @@ -0,0 +1,233 @@ + + + + + + RichTextEditor + + + + +
+ + diff --git a/example/src/Examples/Advanced/Editor/index.html b/example/src/Examples/Advanced/Editor/index.html new file mode 100644 index 0000000..05379ea --- /dev/null +++ b/example/src/Examples/Advanced/Editor/index.html @@ -0,0 +1,33 @@ + + + + + + RichTextEditor + + + +
+ + + diff --git a/example/src/Examples/Advanced/Editor/index.tsx b/example/src/Examples/Advanced/Editor/index.tsx new file mode 100644 index 0000000..901a759 --- /dev/null +++ b/example/src/Examples/Advanced/Editor/index.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import { AdvancedEditor } from './AdvancedEditor'; + +/** + * This is the entrypoint for the "web" part of our editor that will be built with vite + */ +const container = document.getElementById('root'); +const root = createRoot(container!); +root.render(); diff --git a/example/src/Examples/Advanced/Editor/tsconfig.json b/example/src/Examples/Advanced/Editor/tsconfig.json new file mode 100644 index 0000000..6ffb2cd --- /dev/null +++ b/example/src/Examples/Advanced/Editor/tsconfig.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "_version": "2.0.0", + "compilerOptions": { + "lib": ["dom", "dom.iterable", "esnext"], + "module": "esnext", + "moduleResolution": "bundler", + "target": "es2015", + + "allowJs": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true, + "jsx": "react-jsx", + "noEmit": true, + "noFallthroughCasesInSwitch": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "paths": { + "tentap": ["../../../../../src/Editor/useTenTap"] + } + }, + } \ No newline at end of file diff --git a/example/src/Examples/Advanced/Editor/vite.config.ts b/example/src/Examples/Advanced/Editor/vite.config.ts new file mode 100644 index 0000000..9281880 --- /dev/null +++ b/example/src/Examples/Advanced/Editor/vite.config.ts @@ -0,0 +1,28 @@ +import { resolve } from 'path'; +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import { viteSingleFile } from 'vite-plugin-singlefile'; + +// This config is used to build the web editor into a single file + +export default defineConfig({ + root: 'src/Examples/Advanced/Editor/', + build: { + outDir: 'build', + }, + resolve: { + alias: [ + { + find: 'tentap', + replacement: resolve( + __dirname, + '../../../../../src/Editor/useTenTap.tsx' + ), + }, + ], + }, + plugins: [react(), viteSingleFile()], + server: { + port: 3000, + }, +}); diff --git a/example/src/Examples/Advanced/README.md b/example/src/Examples/Advanced/README.md new file mode 100644 index 0000000..d972194 --- /dev/null +++ b/example/src/Examples/Advanced/README.md @@ -0,0 +1,9 @@ +# Advanced Editor + +1. Create index.html (or use one from lib?) +2. Create entrypoint index.tsx +3. Create tsconfig +4. Add to ignore on root tsconfig +5. Add commands to package.json +6. In entry point use useTenTap +7. Add -D @tiptap/react @tiptap/pm diff --git a/src/Editor/Tiptap.tsx b/src/Editor/Tiptap.tsx index c83e36b..d3435e0 100644 --- a/src/Editor/Tiptap.tsx +++ b/src/Editor/Tiptap.tsx @@ -1,127 +1,8 @@ -import debounce from 'lodash/debounce'; -import React, { useEffect } from 'react'; -import { EditorContent, useEditor } from '@tiptap/react'; -import { Editor } from '@tiptap/core'; -// import TextStyle from '@tiptap/extension-text-style'; -// import { Color } from '@tiptap/extension-color'; -// import Highlight from '@tiptap/extension-highlight'; -import { EditorMessage, EditorMessageType } from '../types/Messaging'; -import { EditorUpdateSettings } from '../types/Actions'; -import focusListener from './utils/focusListener'; -import { TenTapStartKit } from './plugins/StarterKit'; -import { UnderlineBridge } from './plugins/underline'; -import { EditorState } from '../types/EditorState'; -import { TaskListBridge } from './plugins/tasklist'; -import { LinkBridge } from './plugins/link'; -import { ColorBridge } from './plugins/color'; -import { HighlightBridge } from './plugins/highlight'; -import { CoreBridge } from './plugins/core'; -import { ImageBridge } from './plugins/image'; -// import { blueBackgroundPlugin } from './plugins/HighlightSelection'; - -const tenTapExtensions = [ - // blueBackgroundPlugin, - TenTapStartKit, - UnderlineBridge, - ImageBridge, - TaskListBridge, - LinkBridge, - ColorBridge, - HighlightBridge, - CoreBridge, -].filter( - (e) => !window.whiteListPlugins || window.whiteListPlugins.includes(e.name) -); - -function filterExists(object: T): object is NonNullable { - return object !== null && object !== undefined; -} - -const extensions = tenTapExtensions - .map((e) => e.tiptapExtension) - .filter(filterExists) - .flat(); - -const content = window.initialContent || ''; - -const sendMessage = (message: EditorMessage) => { - // @ts-ignore TODO fix type - window.ReactNativeWebView?.postMessage(JSON.stringify(message)); -}; - -const sendStateUpdate = debounce((editor: Editor) => { - let payload = { - // core - isReady: true, - isFocused: focusListener.isFocused, - }; - - const state = tenTapExtensions.reduce((acc, e) => { - return Object.assign(acc, e.extendEditorState(editor)); - }, payload) as EditorState; - - sendMessage({ - type: EditorMessageType.StateUpdate, - payload: state, - }); -}, 10); +import { EditorContent } from '@tiptap/react'; +import { useTenTap } from './useTenTap'; export default function Tiptap() { - const editor = useEditor({ - extensions, - content, - onCreate: () => - sendMessage({ type: EditorMessageType.EditorReady, payload: null }), - onUpdate: (onUpdate) => sendStateUpdate(onUpdate.editor), - onSelectionUpdate: (onUpdate) => sendStateUpdate(onUpdate.editor), - onTransaction: (onUpdate) => sendStateUpdate(onUpdate.editor), - }); - - useEffect(() => { - if (!editor) return; - // Subscribe to editor message - const handleEditorAction = (action: any) => { - tenTapExtensions.forEach((e) => { - e.onBridgeMessage(editor, action, sendMessage); - }); - if (action.type === EditorUpdateSettings.UpdateScrollThresholdAndMargin) { - editor.setOptions({ - editorProps: { - scrollThreshold: { - top: 0, - bottom: action.payload, - right: 0, - left: 0, - }, - scrollMargin: { top: 0, bottom: action.payload, right: 0, left: 0 }, - }, - }); - } - }; - const handleWebviewMessage = (event: MessageEvent | Event) => { - if (!(event instanceof MessageEvent)) return; // TODO check android - const { type, payload } = JSON.parse(event.data) as EditorMessage; - console.log('Received message from webview', { type, payload }); - switch (type) { - case EditorMessageType.Action: - if (payload.type === EditorUpdateSettings.Focus) { - editor.commands.focus(payload.payload); - } - // Handle actions - handleEditorAction(payload); - break; - } - }; - // We need to listen to both window and document events because some platform get - // webview messages from window and some from document - window.addEventListener('message', handleWebviewMessage); - document.addEventListener('message', handleWebviewMessage); - - return () => { - window.removeEventListener('message', handleWebviewMessage); - document.removeEventListener('message', handleWebviewMessage); - }; - }, [editor]); + const editor = useTenTap(); return ; } diff --git a/src/Editor/tsconfig.json b/src/Editor/tsconfig.json index c1762d3..783f07e 100644 --- a/src/Editor/tsconfig.json +++ b/src/Editor/tsconfig.json @@ -1,24 +1,22 @@ { - "$schema": "https://json.schemastore.org/tsconfig", - "display": "Create React App", - "_version": "2.0.0", - - "compilerOptions": { - "lib": ["dom", "dom.iterable", "esnext"], - "module": "esnext", - "moduleResolution": "bundler", - "target": "es2015", - - "allowJs": true, - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "isolatedModules": true, - "jsx": "react-jsx", - "noEmit": true, - "noFallthroughCasesInSwitch": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true - } - } \ No newline at end of file + "$schema": "https://json.schemastore.org/tsconfig", + "_version": "2.0.0", + "compilerOptions": { + "lib": ["dom", "dom.iterable", "esnext"], + "module": "esnext", + "moduleResolution": "bundler", + "target": "es2015", + + "allowJs": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true, + "jsx": "react-jsx", + "noEmit": true, + "noFallthroughCasesInSwitch": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true + } +} \ No newline at end of file diff --git a/src/Editor/useTenTap.tsx b/src/Editor/useTenTap.tsx new file mode 100644 index 0000000..3b97ff4 --- /dev/null +++ b/src/Editor/useTenTap.tsx @@ -0,0 +1,122 @@ +import debounce from 'lodash/debounce'; +import { useEffect } from 'react'; +import { useEditor } from '@tiptap/react'; +import { Editor } from '@tiptap/core'; +import { EditorMessage, EditorMessageType } from '../types/Messaging'; +import { EditorUpdateSettings } from '../types/Actions'; +import focusListener from './utils/focusListener'; +import { TenTapStartKit } from './plugins/StarterKit'; +import { UnderlineBridge } from './plugins/underline'; +import { EditorState } from '../types/EditorState'; +import { TaskListBridge } from './plugins/tasklist'; +import { LinkBridge } from './plugins/link'; +import { ColorBridge } from './plugins/color'; +import { HighlightBridge } from './plugins/highlight'; +import { CoreBridge } from './plugins/core'; +import { ImageBridge } from './plugins/image'; + +const tenTapExtensions = [ + TenTapStartKit, + UnderlineBridge, + ImageBridge, + TaskListBridge, + LinkBridge, + ColorBridge, + HighlightBridge, + CoreBridge, +].filter( + (e) => !window.whiteListPlugins || window.whiteListPlugins.includes(e.name) +); + +function filterExists(object: T): object is NonNullable { + return object !== null && object !== undefined; +} + +const extensions = tenTapExtensions + .map((e) => e.tiptapExtension) + .filter(filterExists) + .flat(); + +const content = window.initialContent || ''; + +const sendMessage = (message: EditorMessage) => { + // @ts-ignore TODO fix type + window.ReactNativeWebView?.postMessage(JSON.stringify(message)); +}; + +const sendStateUpdate = debounce((editor: Editor) => { + let payload = { + // core + isReady: true, + isFocused: focusListener.isFocused, + }; + + const state = tenTapExtensions.reduce((acc, e) => { + return Object.assign(acc, e.extendEditorState(editor)); + }, payload) as EditorState; + + sendMessage({ + type: EditorMessageType.StateUpdate, + payload: state, + }); +}, 10); + +export const useTenTap = () => { + const editor = useEditor({ + extensions, + content, + onCreate: () => + sendMessage({ type: EditorMessageType.EditorReady, payload: null }), + onUpdate: (onUpdate) => sendStateUpdate(onUpdate.editor), + onSelectionUpdate: (onUpdate) => sendStateUpdate(onUpdate.editor), + onTransaction: (onUpdate) => sendStateUpdate(onUpdate.editor), + }); + + useEffect(() => { + if (!editor) return; + // Subscribe to editor message + const handleEditorAction = (action: any) => { + tenTapExtensions.forEach((e) => { + e.onBridgeMessage(editor, action, sendMessage); + }); + if (action.type === EditorUpdateSettings.UpdateScrollThresholdAndMargin) { + editor.setOptions({ + editorProps: { + scrollThreshold: { + top: 0, + bottom: action.payload, + right: 0, + left: 0, + }, + scrollMargin: { top: 0, bottom: action.payload, right: 0, left: 0 }, + }, + }); + } + }; + const handleWebviewMessage = (event: MessageEvent | Event) => { + if (!(event instanceof MessageEvent)) return; // TODO check android + const { type, payload } = JSON.parse(event.data) as EditorMessage; + console.log('Received message from webview', { type, payload }); + switch (type) { + case EditorMessageType.Action: + if (payload.type === EditorUpdateSettings.Focus) { + editor.commands.focus(payload.payload); + } + // Handle actions + handleEditorAction(payload); + break; + } + }; + // We need to listen to both window and document events because some platform get + // webview messages from window and some from document + window.addEventListener('message', handleWebviewMessage); + document.addEventListener('message', handleWebviewMessage); + + return () => { + window.removeEventListener('message', handleWebviewMessage); + document.removeEventListener('message', handleWebviewMessage); + }; + }, [editor]); + + return editor; +}; diff --git a/src/RichText/RichText.tsx b/src/RichText/RichText.tsx index 1eb5c28..b282467 100644 --- a/src/RichText/RichText.tsx +++ b/src/RichText/RichText.tsx @@ -15,9 +15,10 @@ import type { EditorInstance } from '../types'; interface RichTextProps extends WebViewProps { editor: EditorInstance; - DEV?: boolean; avoidIosKeyboard?: boolean; autofocus?: boolean; + customSource?: string; + DEV?: boolean; } const styles = StyleSheet.create({ @@ -37,13 +38,14 @@ const DEV_SERVER_URL = 'http://localhost:3000'; export const RichText = ({ DEV, editor, + customSource, avoidIosKeyboard, autofocus, }: RichTextProps) => { const { keyboardHeight: iosKeyboardHeight } = useKeyboard(); const source: WebViewProps['source'] = DEV ? { uri: DEV_SERVER_URL } - : { html: editorHTML }; + : { html: customSource || editorHTML }; const onWebviewMessage = (event: WebViewMessageEvent) => { const { data } = event.nativeEvent; diff --git a/tsconfig.json b/tsconfig.json index 672ec26..0bd7b51 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,5 +25,5 @@ "target": "esnext", "verbatimModuleSyntax": true, }, - "exclude": ["./src/Editor","./website"] + "exclude": ["./src/Editor","./website", "./example/src/Examples/Advanced/Editor"] } diff --git a/yarn.lock b/yarn.lock index ba15098..87855f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4578,6 +4578,18 @@ __metadata: languageName: node linkType: hard +"@tiptap/extension-bubble-menu@npm:^2.2.1": + version: 2.2.1 + resolution: "@tiptap/extension-bubble-menu@npm:2.2.1" + dependencies: + tippy.js: ^6.3.7 + peerDependencies: + "@tiptap/core": ^2.0.0 + "@tiptap/pm": ^2.0.0 + checksum: 5ea8dac3044f14b02fb70964b1c8c8da834d13b3ef7450af61a2a06b6d9af06031344f45d5be5d05dd01b62b1f45a8073ea40d4c0732350f18f37c50883f4099 + languageName: node + linkType: hard + "@tiptap/extension-bullet-list@npm:^2.1.16": version: 2.1.16 resolution: "@tiptap/extension-bullet-list@npm:2.1.16" @@ -4647,6 +4659,18 @@ __metadata: languageName: node linkType: hard +"@tiptap/extension-floating-menu@npm:^2.2.1": + version: 2.2.1 + resolution: "@tiptap/extension-floating-menu@npm:2.2.1" + dependencies: + tippy.js: ^6.3.7 + peerDependencies: + "@tiptap/core": ^2.0.0 + "@tiptap/pm": ^2.0.0 + checksum: 453a949e7feadfa58203faf2c8fc49f7e5d6d868ffd8605e264a1a94146f2fda258ffbfef4c0f42c14e0090d69e8567b4a56b309f59dff74bccb1a9cb15977f6 + languageName: node + linkType: hard + "@tiptap/extension-gapcursor@npm:^2.1.16": version: 2.1.16 resolution: "@tiptap/extension-gapcursor@npm:2.1.16" @@ -4842,6 +4866,32 @@ __metadata: languageName: node linkType: hard +"@tiptap/pm@npm:^2.2.1": + version: 2.2.1 + resolution: "@tiptap/pm@npm:2.2.1" + dependencies: + prosemirror-changeset: ^2.2.1 + prosemirror-collab: ^1.3.1 + prosemirror-commands: ^1.5.2 + prosemirror-dropcursor: ^1.8.1 + prosemirror-gapcursor: ^1.3.2 + prosemirror-history: ^1.3.2 + prosemirror-inputrules: ^1.3.0 + prosemirror-keymap: ^1.2.2 + prosemirror-markdown: ^1.12.0 + prosemirror-menu: ^1.2.4 + prosemirror-model: ^1.19.4 + prosemirror-schema-basic: ^1.2.2 + prosemirror-schema-list: ^1.3.0 + prosemirror-state: ^1.4.3 + prosemirror-tables: ^1.3.5 + prosemirror-trailing-node: ^2.0.7 + prosemirror-transform: ^1.8.0 + prosemirror-view: ^1.32.7 + checksum: 6efaf572b1a2b97dd6c89fd0cb66783da8f9d2a35829a046901790d0a7de61c2652d47208b73436138b15c67aa6547320cdf6021cd922b1dac40df3a6ce3b357 + languageName: node + linkType: hard + "@tiptap/react@npm:^2.1.16": version: 2.1.16 resolution: "@tiptap/react@npm:2.1.16" @@ -4857,6 +4907,21 @@ __metadata: languageName: node linkType: hard +"@tiptap/react@npm:^2.2.1": + version: 2.2.1 + resolution: "@tiptap/react@npm:2.2.1" + dependencies: + "@tiptap/extension-bubble-menu": ^2.2.1 + "@tiptap/extension-floating-menu": ^2.2.1 + peerDependencies: + "@tiptap/core": ^2.0.0 + "@tiptap/pm": ^2.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + checksum: e6bdad76a5283562ff59988f46e5cb5aec12756be29931a035799010df18a7dfa7eca1907801aecba8418e0210cd19f91cbfef0205294e898b8bcd53dbda4fcd + languageName: node + linkType: hard + "@tiptap/starter-kit@npm:^2.1.16": version: 2.1.16 resolution: "@tiptap/starter-kit@npm:2.1.16" @@ -16738,7 +16803,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-changeset@npm:^2.2.0": +"prosemirror-changeset@npm:^2.2.0, prosemirror-changeset@npm:^2.2.1": version: 2.2.1 resolution: "prosemirror-changeset@npm:2.2.1" dependencies: @@ -16747,7 +16812,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-collab@npm:^1.3.0": +"prosemirror-collab@npm:^1.3.0, prosemirror-collab@npm:^1.3.1": version: 1.3.1 resolution: "prosemirror-collab@npm:1.3.1" dependencies: @@ -16756,7 +16821,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-commands@npm:^1.0.0, prosemirror-commands@npm:^1.3.1": +"prosemirror-commands@npm:^1.0.0, prosemirror-commands@npm:^1.3.1, prosemirror-commands@npm:^1.5.2": version: 1.5.2 resolution: "prosemirror-commands@npm:1.5.2" dependencies: @@ -16767,7 +16832,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-dropcursor@npm:^1.5.0": +"prosemirror-dropcursor@npm:^1.5.0, prosemirror-dropcursor@npm:^1.8.1": version: 1.8.1 resolution: "prosemirror-dropcursor@npm:1.8.1" dependencies: @@ -16778,7 +16843,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-gapcursor@npm:^1.3.1": +"prosemirror-gapcursor@npm:^1.3.1, prosemirror-gapcursor@npm:^1.3.2": version: 1.3.2 resolution: "prosemirror-gapcursor@npm:1.3.2" dependencies: @@ -16790,7 +16855,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-history@npm:^1.0.0, prosemirror-history@npm:^1.3.0": +"prosemirror-history@npm:^1.0.0, prosemirror-history@npm:^1.3.0, prosemirror-history@npm:^1.3.2": version: 1.3.2 resolution: "prosemirror-history@npm:1.3.2" dependencies: @@ -16812,7 +16877,17 @@ __metadata: languageName: node linkType: hard -"prosemirror-keymap@npm:^1.0.0, prosemirror-keymap@npm:^1.1.2, prosemirror-keymap@npm:^1.2.0": +"prosemirror-inputrules@npm:^1.3.0": + version: 1.4.0 + resolution: "prosemirror-inputrules@npm:1.4.0" + dependencies: + prosemirror-state: ^1.0.0 + prosemirror-transform: ^1.0.0 + checksum: b893eff382b585aa934e41a7bcbb02cd9ce5199bc6e939ef3f1629aeaf181320f2b52a0d088cb6432aa10c4536c3b5ea67a15e66ef24714a3b3f9e89d0f29ef4 + languageName: node + linkType: hard + +"prosemirror-keymap@npm:^1.0.0, prosemirror-keymap@npm:^1.1.2, prosemirror-keymap@npm:^1.2.0, prosemirror-keymap@npm:^1.2.2": version: 1.2.2 resolution: "prosemirror-keymap@npm:1.2.2" dependencies: @@ -16822,7 +16897,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-markdown@npm:^1.10.1": +"prosemirror-markdown@npm:^1.10.1, prosemirror-markdown@npm:^1.12.0": version: 1.12.0 resolution: "prosemirror-markdown@npm:1.12.0" dependencies: @@ -16832,7 +16907,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-menu@npm:^1.2.1": +"prosemirror-menu@npm:^1.2.1, prosemirror-menu@npm:^1.2.4": version: 1.2.4 resolution: "prosemirror-menu@npm:1.2.4" dependencies: @@ -16844,7 +16919,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-model@npm:^1.0.0, prosemirror-model@npm:^1.16.0, prosemirror-model@npm:^1.18.1, prosemirror-model@npm:^1.19.0, prosemirror-model@npm:^1.8.1": +"prosemirror-model@npm:^1.0.0, prosemirror-model@npm:^1.16.0, prosemirror-model@npm:^1.18.1, prosemirror-model@npm:^1.19.0, prosemirror-model@npm:^1.19.4, prosemirror-model@npm:^1.8.1": version: 1.19.4 resolution: "prosemirror-model@npm:1.19.4" dependencies: @@ -16853,7 +16928,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-schema-basic@npm:^1.2.0": +"prosemirror-schema-basic@npm:^1.2.0, prosemirror-schema-basic@npm:^1.2.2": version: 1.2.2 resolution: "prosemirror-schema-basic@npm:1.2.2" dependencies: @@ -16862,7 +16937,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-schema-list@npm:^1.2.2": +"prosemirror-schema-list@npm:^1.2.2, prosemirror-schema-list@npm:^1.3.0": version: 1.3.0 resolution: "prosemirror-schema-list@npm:1.3.0" dependencies: @@ -16873,7 +16948,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-state@npm:^1.0.0, prosemirror-state@npm:^1.2.2, prosemirror-state@npm:^1.3.1, prosemirror-state@npm:^1.4.1": +"prosemirror-state@npm:^1.0.0, prosemirror-state@npm:^1.2.2, prosemirror-state@npm:^1.3.1, prosemirror-state@npm:^1.4.1, prosemirror-state@npm:^1.4.3": version: 1.4.3 resolution: "prosemirror-state@npm:1.4.3" dependencies: @@ -16884,7 +16959,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-tables@npm:^1.3.0": +"prosemirror-tables@npm:^1.3.0, prosemirror-tables@npm:^1.3.5": version: 1.3.5 resolution: "prosemirror-tables@npm:1.3.5" dependencies: @@ -16897,7 +16972,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-trailing-node@npm:^2.0.2": +"prosemirror-trailing-node@npm:^2.0.2, prosemirror-trailing-node@npm:^2.0.7": version: 2.0.7 resolution: "prosemirror-trailing-node@npm:2.0.7" dependencies: @@ -16912,7 +16987,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-transform@npm:^1.0.0, prosemirror-transform@npm:^1.1.0, prosemirror-transform@npm:^1.2.1, prosemirror-transform@npm:^1.7.0, prosemirror-transform@npm:^1.7.3": +"prosemirror-transform@npm:^1.0.0, prosemirror-transform@npm:^1.1.0, prosemirror-transform@npm:^1.2.1, prosemirror-transform@npm:^1.7.0, prosemirror-transform@npm:^1.7.3, prosemirror-transform@npm:^1.8.0": version: 1.8.0 resolution: "prosemirror-transform@npm:1.8.0" dependencies: @@ -16921,7 +16996,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-view@npm:^1.0.0, prosemirror-view@npm:^1.1.0, prosemirror-view@npm:^1.13.3, prosemirror-view@npm:^1.27.0, prosemirror-view@npm:^1.28.2, prosemirror-view@npm:^1.31.0": +"prosemirror-view@npm:^1.0.0, prosemirror-view@npm:^1.1.0, prosemirror-view@npm:^1.13.3, prosemirror-view@npm:^1.27.0, prosemirror-view@npm:^1.28.2, prosemirror-view@npm:^1.31.0, prosemirror-view@npm:^1.32.7": version: 1.32.7 resolution: "prosemirror-view@npm:1.32.7" dependencies: @@ -19394,6 +19469,8 @@ __metadata: "@react-native/typescript-config": 0.73.1 "@react-navigation/native": ^6.1.9 "@react-navigation/native-stack": ^6.9.17 + "@tiptap/pm": ^2.2.1 + "@tiptap/react": ^2.2.1 babel-plugin-inline-import: ^3.0.0 babel-plugin-module-resolver: ^5.0.0 pod-install: ^0.1.0 @@ -19402,6 +19479,7 @@ __metadata: react-native-safe-area-context: ^4.8.2 react-native-screens: ^3.29.0 react-native-webview: 13.6.4 + vite: ^5.0.12 languageName: unknown linkType: soft