Skip to content

feat: enhance text cursor positioning in blocks #1894

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

must
Copy link

@must must commented Jul 30, 2025

  • Added offset calculation for cursor position within block's inline content.
  • Updated setTextCursorPosition to accept numeric offsets, allowing precise cursor placement.
  • Improved handling of blocks with no inline content and wrapper nodes.
  • Documented new functionality in relevant areas.

Copy link

vercel bot commented Jul 30, 2025

@must is attempting to deploy a commit to the TypeCell Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

sentry-io bot commented Jul 30, 2025

🔍 Existing Issues For Review

Your pull request is modifying functions with the following pre-existing issues:

📄 File: packages/core/src/api/blockManipulation/selections/textCursorPosition.ts

Function Unhandled Issue
BlockNoteEditor.setTextCursorPosition Error: Block with ID initialBlockId not found /
Event Count: 1 Affected Users: 1

Did you find this useful? React with a 👍 or 👎

@nperez0111
Copy link
Contributor

Hi @must, really appreciate you digging into this. While I agree that we need something like this, I don't think that this particular solution is what we are looking for right now.

In this PR I laid out some of the things that we want to move toward in future versions of blocknote: #1756
What will be of interest to you is the Location API and this is the file it is referring to: https://github.com/TypeCellOS/BlockNote/blob/api-design/packages/core/src/editor/Location.ts

Essentially we are looking to move toward an API that does include character offsets, but in a way that the user doesn't need to specifically always use character offsets. What you've implemented is a good stepping stone towards that sort of an API, but we will need to take this further before introducing more concepts to our existing API.

@must
Copy link
Author

must commented Jul 31, 2025

Hi @must, really appreciate you digging into this. While I agree that we need something like this, I don't think that this particular solution is what we are looking for right now.

In this PR I laid out some of the things that we want to move toward in future versions of blocknote: #1756 What will be of interest to you is the Location API and this is the file it is referring to: https://github.com/TypeCellOS/BlockNote/blob/api-design/packages/core/src/editor/Location.ts

Essentially we are looking to move toward an API that does include character offsets, but in a way that the user doesn't need to specifically always use character offsets. What you've implemented is a good stepping stone towards that sort of an API, but we will need to take this further before introducing more concepts to our existing API.

Thanks for the thoughtful feedback @nperez0111 . I really appreciate the forward-looking approach here. I just started using BlockNote on a project and it’s awesome. While building with table updates, preserving the cursor position was a blocker which led me to issue #1815 .

I’m fully on board with the Location API vision you’ve sketched in the ADR and your plan to evolve the editor’s Transform API. My recent offset-based patch was simply a quick fix to unblock what I needed to build.

What I’d love to know is can we land a minimal interim update on main that keeps the cursor position during table block updates? I'm happy to contribute as much as possible but I'm just starting out with this repo so I'm trying to get the least effort highest reward contribution here as I get more familiar with what you've built so far (quite a lot).

Let me know what’s reasonable in the short term and how I can help shape the long-term version.

@nperez0111
Copy link
Contributor

@must so the root issue you are running into is around preserving the cursor during block updates? I think that is a great place to start and definitely something that we should improve on.

Would that unblock you on what you are building? (what are you building, btw, always nice to hear).

I can help guide you on where that issue is, if so

@must
Copy link
Author

must commented Jul 31, 2025

@nperez0111 This is much appreciated!

So yeah the root cause that led me down this path is table block updates resulting in the cursor jumping towards the end. Building an LLM-assisted quote-generation tool with real-time, collaborative editing capabilities which requires dynamic updates to table cells while keeping the cursor intact. It's part of Narrative

I might still be missing some things here, but any pointers you can share would be super helpful

@nperez0111
Copy link
Contributor

@must Looks cool!

Which sorts of table block updates you are referring to?

@must
Copy link
Author

must commented Jul 31, 2025

@nperez0111 thanks!

As simple as user makes an input (keystroke) on a cell of the same table and we modify another next to it to reflect some change in calculations then using updateBlock on said table / cell contents results in the cursor jumping to the end of the doc.

If I'm not mistaken, I have to update the whole table block as there's no ids on the cells?

@nperez0111
Copy link
Contributor

nperez0111 commented Jul 31, 2025

@must yep, you are right. Right now, tables are one of our most complicated blocks since cells act as a sort of block - we are looking to support nested blocks in the future, and tables will likely be one of them.

But, for now. I think that it is sufficient to work on the updateBlock API, and trying to preserve the selection if possible. I made an update to a table cell, and narrowed it down to this code which definitely moves the selection. I think that what we will probably want to do here is to:

  1. Keep the selection if it can still "fit" within the block that it was in (i.e. if the block update made the block shorter, clamp the selection restoration to the end of the block).
  2. See if any other code paths update the selection positions, and apply a similar fix.

Once we have this in-place, you should be able to update the content of a table and the selection will be preserved where it was.

@must
Copy link
Author

must commented Aug 6, 2025

@nperez0111 thanks for the pointers. And sorry for the delay. I tried a few approaches to preserve the cursor. The real blocker is that table cells don’t have IDs. This is especially problematic when multiple cells change and the cursor is on a subsequent cell. Previous character changes needs to be accounted for then otherwise the selection would jump by the previous changes). I've pushed an example that does not rely on cell ids and this still presents the aforementioned issue.

I'd imagine nested blocks for tables is the approach you were referring to here?

We could hack around it with deltas, but that feels brittle. Easiest way seems to add ids to cells so we can restore via cell id and localOffset. What do you think?

@must must reopened this Aug 6, 2025
@nperez0111
Copy link
Contributor

I will take a look at the specifics later but yes I referring to nested blocks where tables could be a container and the cells have IDs but we can't support that right now (and it would be a lot of work to do so)

I would suggest doing something like figuring out which cell within the table the selection is within (row and column) and move the selection back to that cell if possible (i.e. the row and column still exist). Then from there character offsets will be able to restore it better once they are implemented

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

Successfully merging this pull request may close these issues.

2 participants