Reference to `EditorView` inside of `StateField.apply`?

I’m trying to write a plugin whose state holds the the viewport rectangle of the selection. I thought that I could simply use apply to be notified of any changes to the selection, use EditorView.coordsAtPos to compute the coordinates, and then store those as the plugin’s state. However, apply doesn’t get a reference to the editor view.

I hacked around this by implementing PluginSpec.view.update and then storing a reference to the view on this.[plugin-name].view and then reading this.view inside of apply, however this feels very very wrong.

I’ve also considered computing the new state inside of view.update then passing it as the meta of a transaction to be picked up by state.apply, but this seems like a very roundabout way of doing things.

Is there some cleaner way to do this?

Is there a reason you’re trying to use a plugin to hold selection state? That’s covered by view.state.selection, and if view is accessible, then the plugin itself is unnecessary.

Is is usually easier to hold view-related state in a plugin view. The state must be able to exist and update without the view, and thus generally shouldn’t have a data dependency on it.

The problem is that my state depends on the result of DOM measurements that I can only do on the view. For instance: if the selection covers more than x lines of text, state should be A otherwise state should be B. Ideally line layout should be stored in or at least derivable from state, but that’s not the case, so the view is the only place that has that information.

Here’s a better example: I have an inline node inside a paragraph that functions much like a footnote indicator in the footnotes example. When that node is clicked I want to insert another node inside that same paragraph at the position that’s after the last character on the same line as the clicked element. The inserted node’s inline is true but its css display attribute is "block" to give the appearance of content appearing in the the gap between two consecutive lines. The problem is that calculating the position corresponding to the last character “on the same line as the clicked element” is something I can only do with access to the view.

(In the second example I actually wouldn’t need to hook into apply or to store any state, instead appendTransaction might be the better option, but that method also lacks access to the view.)

Wouldn’t that be something that you’d determine in the (imperative) click handler, which can trivially have access to the view?