Conditionally showing Widgets using a StateField

I’m using the latest versions of the CM6 libs (codemirror/state: 6.2.0, codemirror/view: 6.9.2), and I’ve created an Extension that returns a StateField. The StateField outputs both a block decoration and a replacement decoration for each markdown image tag it finds in the syntaxTree. So far, this works. Here’s the StateField:

const imagesField = StateField.define({
  create(state) {
    return decorate(state);
  },
  update(value, transaction) {
    if (transaction.docChanged) {
      return decorate(transaction.state);
    }

    return value.map(transaction.changes);
  },
  provide(field) {
    return EditorView.decorations.from(field);
  }
});

And this is the decorate function:

const decorate = state => {
  const decorations = [];

  syntaxTree(state).iterate({
    enter: ({ type, from, to }) => {
      if (type.name === "Image") {
        const result = imageRegex.exec(state.doc.sliceString(from, to));

        if (result && result.groups && result.groups.url) {
          decorations.push(imageDecoration({ url: result.groups.url }).range(state.doc.lineAt(from).from));
          decorations.push(replacementDecoration({ url: result.groups.url }).range(from, to));
        }
      }
    }
  });

  return decorations.length > 0 ? RangeSet.of(decorations) : Decoration.none;
};

Now, I’m trying to make sure those decorations only show when the cursor is NOT within the image tag. The idea is to have inline images throughout the document that are only visible when the user is not actively editing the image tag itself.

I started writing code the StateField’s update method to update/filter the RangeSet that’s returned based on cursor position, but it’s not working as expected. Is there a better way to accomplish this?

1 Like

No, this seems reasonable. As an optimization, you might be able to keep both the ‘full’ range set and the filtered one — have update logic that checks if the cursor is inside a range in the full set, returns the full set if not, and a filtered version if so.