NodeView inside document selection

I’m using NodeView and would like it to apply a style (e.g. shaded blue overlay) to indicate when its node is inside a selection (e.g. an enclosing TextSelection / AllSelection / CellSelection / etc).

I’ve considered and ruled out:

  • Applying an inline decoration over the range of the selection (not supported — NodeView is only notified of node decorations)
  • Using a NodeView API that is called when document selection changes (doesn’t exist)
  • Using a CSS property / pseudo selector based on DOM selection (couldn’t find anything appropriate)

It seems like I need to write a plugin that applies a node decoration to each node (that I want styled) and then use the update hook to apply the styling. Doing this inefficiently seems simple — after each transaction traverse the document between the current selection Node#nodesBetween. To do this efficiently I think I’d need to track positions of node insertions/deletions/shifts in the plugin, and then find positions falling within the selection bounds during selection changes.

Am I missing anything here, or is this the best way to solve the problem? This feels like something that would be good to incorporate directly into ProseMirror, as it seems like it would be a fairly common task when dealing with NodeView.

Update: I ended up implementing an alternative approach, which is to create an observable of the editor selection in a plugin (fed by the plugin view update hook), and pass it down to the node view. The node view then subscribes to selection changes, and uses getPos() to check if it’s in bounds, and updates itself based on that. Thanks @rifat for the suggestion from Atlassian’s editor https://bitbucket.org/atlassian/atlaskit-mk-2/src/116c9ac88c140c03c7b83a6c9eced7b0b214813d/packages/editor/editor-core/src/nodeviews/ui/wrapper-click-area.tsx#lines-55

3 Likes

Have you profiled this inefficient approach? The selection is rarely very big, and even when it is, iterating over a document is going to be pretty quickly. Unless there are thousands such nodes, I don’t expect this to take any kind of serious time.