Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting scrolling (e.g. on typing) to work in virtualized lists #1355

Closed
krassowski opened this issue Mar 13, 2024 · 5 comments
Closed

Getting scrolling (e.g. on typing) to work in virtualized lists #1355

krassowski opened this issue Mar 13, 2024 · 5 comments

Comments

@krassowski
Copy link

krassowski commented Mar 13, 2024

Describe the issue

When I type in the editor which is out of view, the container in which it is embedded is scrolled revealing the editor. This is thanks to internal CodeMirror logic. This logic calls DocView.scrollIntoView() which in turn calls scrollRectIntoView() method. The scrollRectIntoView tries hard to find out which parent element needs to be scrolled and it succeeds even for the virtualized lists. However, the delta needed to scroll is wrong when the CodeMirror editor is embedded in a virtualized list. This is not surprising - scrollRectIntoView cannot know how much to scroll if some of the elements are hidden by virtualization.

It is currently impossible to cleanly hook into scrollRectIntoView in order to scroll the virtualized list to reveal editor. It is also not possible to listen to consequences of scrollRectIntoView and intervene because scrollTop used by scrollRectIntoView emits a plain event which is indistinguishable from native scroll events invoked by user (and which does not carry the underlying information about the scroll target).

To support the use case of embedding CodeMirror in virtualized lists it would be sufficient if scrollIntoView had a callback/event called/emitted before scrollRectIntoView is called (which would include the scroll target info). The virtualized list owner could then scroll the virtualized list revealing the editor.

Is this a use-case that could be supported?

Browser and platform

No response

Reproduction link

No response

@krassowski
Copy link
Author

I am checking if the new docViewUpdate could help here...

@krassowski
Copy link
Author

No, docViewUpdate does not get called on cursor movement.

I can still use update() but this involves a lot of filtering down of undesirable updates. The problem when used from TypeScript is that view.viewState.scrollTarget is not exposed because viewState is marked as internal. If we could probe whether scrollTarget is defined I can handle this in update listener:

My current solution comes down to:

ViewPlugin.define((view) => {
  return {
    update: () => {
      // @ts-ignore
      const scrollTarget = view.viewState.scrollTarget;
      if (scrollTarget) {
        scrollVirtualizedListToEditor(scrollTarget);
      }
    }
  };
})

or equivalently:

EditorView.updateListener.of((viewUpdate) => {
  // @ts-ignore
  const scrollTarget = viewUpdate.view.viewState.scrollTarget;
  if (scrollTarget) {
      scrollVirtualizedListToEditor(scrollTarget);
  }
})

Would you consider exposing scrollTarget via getter on EditorView? If not, what about having a new scroll entry point like below?

ViewPlugin.define((view) => {
  return {
    scroll: (scrollTarget: ScrollTarget) => {
      scrollVirtualizedListToEditor(scrollTarget);
    }
  };
})

marijnh added a commit to codemirror/view that referenced this issue Mar 14, 2024
FEATURE: The `EditorView.scrollHandler` facet can be used to override or extend
the behavior of the editor when things are scrolled into view.

Issue codemirror/dev#1355
@marijnh
Copy link
Member

marijnh commented Mar 14, 2024

Does patch codemirror/view@1ecb5f1 look like it would work for you?

@krassowski
Copy link
Author

Yes, this looks like it should do it, thank you!

@marijnh
Copy link
Member

marijnh commented Mar 14, 2024

Released as part of @codemirror/view 6.26.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants