9

I'm trying to create a text editor with tiptap using reactjs. I would like to create a button next to each "block" of the editor (paragraph block, blockquote block, codeblock block, ...) that allows the user to add a new empty block just before the selected block. It would look like this (Notion editor) :

Add block below current demo

So the way I tried to do this is to set the cursor's position at the end of the current node :

src/components/blocks/Paragraph.js

const Paragraph = (props) => {
    // ...

    

    return {
        // ...
        <button onMouseDown={() => {
            // ...

            // props.getPos() gives the position at the beginning of the block
            // props.node.nodeSize gives the "length" of the node
            const endPos = props.getPos() + props.node.nodeSize;
            props.editor.commands.focus(endPos);

            // ...
        }}>
             Add block below
        </button>
    }
}

So at this point, it works. But then, when I try to insert a new node at this position...

// It will insert a paragraph node containing text "New block added"
props.editor.commands.insertContent({
    "type":"paragraph",
    "content":[
        {
            "type":"text",
            "text":"New block added"
        }
    ]
})

... I get an error : TypeError: Cannot read property 'nodeType' of null

So, to let you see this error in details, I've made a sandbox on codesandbox.io. To reproduce the error, you just have to focus on the editor, write something random and then click on + button. You should see the error.

Error when adding a new block

Edit react-passing-local-state-to-parent-component

Thanks in advance for your help !

pierre-lgb
  • 842
  • 1
  • 6
  • 15

1 Answers1

19

Current solution


Currently the best solution I've found :

// Last position of the current node (props are available in a react node view: https://tiptap.dev/guide/node-views/react#all-available-props)
const endPos = props.getPos() + props.node.nodeSize

// I focus the start of the editor because
// when the cursor is at the end of the node below which 
// we want to add a block, it doesn't focus the next block
props.editor.commands.focus('start')

props.editor
    .chain()
    .insertContentAt(endPos, {type: "paragraph"})
    .focus(endPos)
    .run()
pierre-lgb
  • 842
  • 1
  • 6
  • 15
  • I was able to get this work with `editor.chain().focus('end').insertContent().run()` so didn't need to get the endPos value. – sirclesam Aug 29 '23 at 20:56
  • 1
    @sirclesam Your code will add content at the end of the editor, not at the end of the current node. Well it's true that I didn't mention what was `endPos`, I'll edit my answer to make it more clear. – pierre-lgb Aug 30 '23 at 15:15
  • 1
    ah yes - My use case is to insert at the end of the editor. Thanks for the clairfication. – sirclesam Aug 31 '23 at 16:38