Widget Placement

Okay I am back with a specific question.
It says in the docs that widgets will use the side parameter to determine the order they should be in if in the same place. The question is how do I put them in the same group as an existing widget if I am not the one who made the original? What determines widgets that are then ordered on the backend? Placed on the same line and ch?
Here is what I have currently. The collapse indicators are from the program I am building the plugin for, the six dots are my own doing and are as far as I can tell inline widgets. (the collapse indicators are built-in to the program but they are not using the CM way to render it from what I was told.)


Bonus question, what are the cm-widgetBuffers? They are img elements and don’t seem to contain anything in particular. They preempt any widget so is it a handler of some kind?

This is purely about widgets that are in the same position. I’m not sure what you mean by ‘in the same group’.

A kludge to prevent browsers from going to pieces when the cursor is next to uneditable content. An src-less image doesn’t show up, but does count as a word boundary, avoiding some bugs like input composition affecting uneditable text, cursors getting stuck or not being drawn at all, and so on.

This is purely about widgets that are in the same position.

Sorry I guess I am making some assumptions here. It sounds like widgets are auto-ordering. To me that implies that they are handled in groups. This means I would have to put two widgets into the same grouping in order to have them interact. However, that might not be how that works.

In the case that is not true. Is there a way to get the position of another widget and then place a widget at that location so that auto-ordering can take place? Is it also possible to make the widget inherit css from the other widget?

Also, would this be the proper way to implement this? It’s what I am currently using.

/* Establishes the view plugin */

import { syntaxTree } from '@codemirror/language';
import { RangeSetBuilder } from '@codemirror/state';
import { Decoration, DecorationSet, EditorView, PluginSpec, PluginValue, ViewPlugin, ViewUpdate, } from '@codemirror/view';
import { HandleWidget } from './HandleWidget';

class HandleViewPlugin implements PluginValue {
  decorations: DecorationSet;

  constructor(view: EditorView) {
    this.decorations = this.buildDecorations(view);
  }

  update(update: ViewUpdate) {
    if (update.docChanged || update.viewportChanged) {
      this.decorations = this.buildDecorations(update.view);
    }
  }

  destroy() {}

  buildDecorations(view: EditorView): DecorationSet {
    const builder = new RangeSetBuilder<Decoration>();

    for (let { from, to } of view.visibleRanges) {
        for (let pos = from; pos <= to; pos++ ) {
            let line = view.state.doc.lineAt(pos);
            builder.add(line.from, line.from, Decoration.widget({
                widget: new HandleWidget(),
                side: -1,
                inlineOrder: true,
            }));
            pos = line.to + 1;
        }
    }

    return builder.finish();
  }
}

const pluginSpec: PluginSpec<HandleViewPlugin> = {
  decorations: (value: HandleViewPlugin) => value.decorations,
};

export const handleRender = ViewPlugin.fromClass(HandleViewPlugin, pluginSpec);