Hey folks!
I’m banging my head around this issue I have
I’m trying to scroll to a specific node in the editor for a given attribute name and value, and we need to scroll to the middle of the scrollable parent container
My current solution is to pass down the parent ref (we are working in React), find the node directly from the DOM, and then use getBoundingClientRect() to calculate the scroll position
Here is the code so far:
const scrollToPosition = debounce(
(node: HTMLElement, scrollableParent?: HTMLElement | null) => {
if (node && scrollableParent) {
const nodeRect = node.getBoundingClientRect();
const parentRect = scrollableParent.getBoundingClientRect();
const scrollPosition =
nodeRect.top -
parentRect.top -
scrollableParent.clientHeight / 2 +
nodeRect.height / 2;
scrollableParent.scrollTo({
top: scrollPosition,
behavior: "smooth",
});
}
},
0
);
export const ScrollAtPosition = Extension.create({
name: "scrollAtPosition",
addCommands() {
return {
scrollAtPositionFromAttributeValue:
(
attr: string,
value: string | boolean,
scrollableParent?: HTMLElement | null
) =>
({ state, tr, view }) => {
const nodes = Array.from(view.dom.querySelectorAll(`[${attr}]`));
const node = nodes.find(
(node: Element) => node.getAttribute(attr) === value
);
if (node) {
console.log("scroll to", attr, value);
scrollToPosition(node as HTMLElement, scrollableParent);
} else {
console.log("couldn't find node to scroll to", attr, value);
}
return true;
},
};
},
});
Unfortunately, it’s very unreliable and doesn’t scroll in the middle of the screen, it’s way off
I hypothesize that the results from getBoundingClientRect() on the DOM node are wrong, but I’m not sure
What’s the idiomatic Prosemirror approach to achieve this?
Important context = we have multiple editors in the same parent container, so we are not in a situation where the editor fills the entire parent container size