I’m trying to create a code viewing interface that blurs lines by default, and reveals them on mouse hover. Here’s what that looks like:
To implement this effect, I’m using a kind of “reactive” decoration. Here’s what that looks like:
class LineBlur implements PluginValue {
decorations: RangeSet<Decoration>
constructor(program: string, on_hover: (ref: number) ⇒ void) {
let builder = new RangeSetBuilder<Decoration>();
let idx = 0;
program.split('\n').forEach((line, i) ⇒ {
let length = line.length + 1;
let mark = Decoration.mark({
tagName: 'span', className='blur-line', attributes: {onmouseover: `window.line_hover(${i})`}
});
builder.add(idx, idx + length, mark);
idx += length;
});
this.decorations = builder.finish();
(window as any).line_hover = (i: number) ⇒ {
on_hover(i);
};
}
update(update: ViewUpdate) {
// pass
}
}
I have two questions.
- To make the effect reactive, I use CSS :hover styles on the blur-line span, and I use a global
window
function to run JS callbacks on hover. Thewindow
hack is obviously gross, is there a better way to do that? - I want to modify this effect such that the lines adjacent to the mouse cursor will also de-blur. For that effect, I think I would need to move the de-blur logic from CSS psuedo-selectors into Javascript. However, I’m not sure how to change the decoration styles dynamically from within a Plugin, any tips on how to do this or avoid the issue?