diff --git a/packages/slate-react/src/hooks/android-input-manager/android-input-manager.ts b/packages/slate-react/src/hooks/android-input-manager/android-input-manager.ts index 8dc58579f7..1e079d36e8 100644 --- a/packages/slate-react/src/hooks/android-input-manager/android-input-manager.ts +++ b/packages/slate-react/src/hooks/android-input-manager/android-input-manager.ts @@ -352,12 +352,25 @@ export function createAndroidInputManager({ insertPositionHint = false } + let inVoidNode = false let [nativeTargetRange] = (event as any).getTargetRanges() if (nativeTargetRange) { targetRange = ReactEditor.toSlateRange(editor, nativeTargetRange, { exactMatch: false, suppressThrow: true, }) + + if ( + nativeTargetRange.collapsed && + nativeTargetRange.startContainer.nodeType === globalThis.Node.TEXT_NODE + ) { + const closestElement = nativeTargetRange.startContainer.parentElement.closest( + '[data-slate-node=element]' + ) + inVoidNode = closestElement?.attributes.hasOwnProperty( + 'data-slate-void' + ) + } } // COMPAT: SelectionChange event is fired after the action is performed, so we @@ -515,12 +528,14 @@ export function createAndroidInputManager({ } case 'insertLineBreak': { + if (inVoidNode) return return scheduleAction(() => Editor.insertSoftBreak(editor), { at: targetRange, }) } case 'insertParagraph': { + if (inVoidNode) return return scheduleAction(() => Editor.insertBreak(editor), { at: targetRange, }) @@ -533,6 +548,7 @@ export function createAndroidInputManager({ case 'insertFromYank': case 'insertReplacementText': case 'insertText': { + if (inVoidNode) return if (data?.constructor.name === 'DataTransfer') { return scheduleAction(() => ReactEditor.insertData(editor, data), { at: targetRange, diff --git a/site/examples/mentions.tsx b/site/examples/mentions.tsx index c95f06c7ef..18bf802b38 100644 --- a/site/examples/mentions.tsx +++ b/site/examples/mentions.tsx @@ -8,11 +8,15 @@ import { withReact, useSelected, useFocused, + useReadOnly, } from 'slate-react' import { Portal } from '../components' import { MentionElement } from './custom-types' +export const IS_ANDROID = + typeof navigator !== 'undefined' && /Android/.test(navigator.userAgent) + const MentionExample = () => { const ref = useRef() const [target, setTarget] = useState() @@ -204,6 +208,7 @@ const Element = props => { const Mention = ({ attributes, children, element }) => { const selected = useSelected() const focused = useFocused() + const readOnly = useReadOnly() const style: React.CSSProperties = { padding: '3px 3px 2px', margin: '0 1px', @@ -221,14 +226,18 @@ const Mention = ({ attributes, children, element }) => { if (element.children[0].italic) { style.fontStyle = 'italic' } + return ( - {children}@{element.character} + {children} + + @{element.character} + ) }