ignoreMutation doesn't block characterData mutation

Hello!

I’m building a custom table using TipTap’s extension-table, extension-table-row, extension-table-cell and extension-table-header. It has similar features to a notion table like add row/table buttons around it, as well as a floating button/menu for each row/column, a custom floating selection overlay, and so on.

For these features, I chose to create a custom TableView class (extending the existing prosemirror’s one, that implements NodeView) and wrap the main Table node in a few divs, to place these custom elements correctly around it.

Here is how I’m defining it:

export class TableView extends TTTableView {
  private tableContainer: HTMLDivElement
  private tableOuterWrapper: HTMLDivElement
  private tableWrapper: HTMLDivElement
  private selectionOverlay: HTMLDivElement

  constructor(props: NodeViewRendererProps, options: TableOptions) {
    const { node } = props
    const { defaultCellMinWidth } = options
    super(node, defaultCellMinWidth)

    // create containers to hold the table and the add buttons
    const tableContainer = document.createElement("div")
    tableContainer.classList.add("tableContainer")

    const tableOuterWrapper = document.createElement("div")
    tableOuterWrapper.classList.add("tableOuterWrapper")

    // add the default table to the container
    tableOuterWrapper.appendChild(this.dom)

    // create the selection overlay view
    const selectionOverlay = document.createElement("div")
    tableOuterWrapper.appendChild(selectionOverlay)

    // add column/row add buttons to the containers
    const addColumnButton = document.createElement("button")
    addColumnButton.classList.add("addColumnButton")
    tableOuterWrapper.appendChild(addColumnButton)
    tableContainer.appendChild(tableOuterWrapper)

    const addRowButton = document.createElement("button")
    addRowButton.classList.add("addRowButton")
    tableContainer.appendChild(addRowButton)

    // dom at this point is the tableWrapper div
    this.tableWrapper = this.dom

    this.tableContainer = tableContainer
    this.tableOuterWrapper = tableOuterWrapper
    this.selectionOverlay = selectionOverlay

    // pass everything to the table view dom node
    this.dom = tableContainer
  }

  // ...
}

That said, I currently have an issue with these wrappers, which is that it’s possible to select them and append content, using the mouse and arrow shortcuts inside the table, specifically to the tableWrapper, which is created by extension-table. The idea is to never allow the Table node to be selected, deleted, or anything outside to be edited.

To fix it I first tried using the contenteditable prop but, as it turns out, it breaks some of the feature it has, like cell focusing (extension-focus), and make is misbehave. I then went to explore the ignoreMutation function, which I already used before, but I found that it’s not blocking the mutations when returning true. I’m able to detect a mutation that adds text to these wrappers, but the text node still gets created, so I had to remove it right away.

Here is the function I’m using:

override ignoreMutation(mutation: ViewMutationRecord): boolean {
  const target = mutation.target as HTMLElement
  const { parentElement } = target

  if (
    mutation.type === "characterData" &&
    (parentElement === this.tableContainer ||
      parentElement === this.tableOuterWrapper ||
      parentElement === this.tableWrapper ||
      parentElement === this.selectionOverlay)
  ) {
    // Remove the text node that was created. Ignoring the mutation should
    // be enough, but apparently it's not, so we remove the node manually.
    if (parentElement.contains(target)) {
      parentElement.removeChild(target)
    }
    return true
  }

  // ignore mutations outside table wrappers/containers
  if ("closest" in target && !target.closest(`.tableOuterWrapper`)) {
    return true
  }

  return super.ignoreMutation(mutation)
}

My questions are:

Is this the expected behavior of ignoreMutation? Shouldn’t it block the mutation? What would you recommend in this case to successfully disallow editing these elements?

I am sorry if this is more TipTap related, but since my question is more about ignoreMutation, I think this is the right place to post.

Thanks in advance.