Set new Node Selection with empty set to true

I’ve created a custom math node view that works great and so I moved on to creating an Input Rule so Prosemirror will replace the matched string with a math representation of it using my custom node view. This also works except for the last bit where I have the Input Rule set the selection to the recently created node view. It sets the selection just fine and my math node view becomes focused. However the second I start typing the node view loses focus!

I noticed through some testing with the Prosemirror devtool that this happens whenever the current selection has its empty boolean set to false (which is being caused by my node selection transaction on my input rule). How do I create a node selection that will select the node but with the empty boolean of the selection set to zero?

Below is my Input Rule:

export const detectFormulaInputRule = new InputRule(detectformulaRegex, (state, match, start, end) => {
    console.log('match!', match, start, end)

    let mqNode = state.schema.nodes.math.create();
    let selection = TextSelection.between(state.doc.resolve(start), state.doc.resolve(end));

    let tr = state.tr.setSelection(
        selection
    ).replaceSelectionWith(
        mqNode
    ).insertText(
        match[0],
        start+1,
        end
    );


    const mqPos = tr.doc.resolve(tr.selection.anchor - tr.selection.$anchor.nodeBefore.nodeSize);
    const mqNodeSelection = new NodeSelection(mqPos);
    tr.setSelection(mqNodeSelection);
    return tr;
})

I’ve also tried to use a regular Selection in place of NodeSelection to no avail:

    const mqNodeSelection = new Selection(mqPos, mqPos);

EDIT: After even more testing, I’ve discovered that the issue happens whenever the node is selected programmatically with a transaction but not when the node view is clicked directly by the user. The selectNode() method on the node view doesn’t fire when clicked by the user so that tells me I may need to modify the selectNode method on the node view so the prosemirror selection is cleared(??) not entirely sure.

How do I create a node selection that will select the node but with the empty boolean of the selection set to zero?

That doesn’t exist. A node selection selects a full node, and is never empty.

Hmm… any ideas as to why the element loses focus when selected by prosemirror then typed into? I’ve looked at your codemirror example for guidance but it doesn’t look like there’s much difference in our approaches. My node view works just fine when I manually click it with my mouse and type into it and it seems to be because in this situation prosemirror doesn’t trigger the node selection… Any advice on how to troubleshoot this would be greatly appreciated.

You haven’t provided the code that deals with nodeView. There could be a lot of things going on due to which it’s not behaving as expected.

in the past i have seen that having a zero width DOM element creates problem with selection.

Here’s the relevant code. It’s pretty basic and barebones. My current guess is that when the updateTextContent() is run, it triggers the deselectNode() function.

class MqBlockView {
    constructor(node, view, getPos) {
        this.view = view;
        this.getPos = getPos;

        this.dom = document.createElement("span");
        this.interface = MathField(this.dom, {
            'onEdit': () => { this.updateTextContent() }
        })
    }

    update(node){
        let contentLatex = this.node.content.content[0].text;
        this.interface.updateLatex(contentLatex);
        return true;
    }

    updateTextContent() {
        let thisLatex = this.interface.getLatex();

        let tr = this.view.state.tr;
        tr.insertText(
            thisLatex,
            this.getPos()+1,
            this.getPos()+1+this.node.content.size
        );
        this.view.dispatch(tr);
    }

    selectNode () {
        this.interface.focus()
    }

    deselectNode(){
        this.interface.blur();
    }

    ignoreMutation() {
        return true;
    }

    stopEvent() {
        return true;
    }
}

I wrote a hacky little work around by not blurring if the last key prosemirror detected was an arrow left or right key… It works I guess for now but I’d much prefer a solid solution lol

deselectNode(){
    const lastKeyCode = this.view.lastKeyCode;
    if (lastKeyCode === 37 || lastKeyCode === 39) {
        return true;  // return and do not blur the math interface
    }
    this.interface.blur();
}