[lexical-table][lexical-playground] Feature: nested tables resize themselves if hasFitNestedTables: true#8183
Conversation
…sform instead of recursion
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| * @returns The horizontal insets of the cell, in pixels. | ||
| */ | ||
| function $calculateCellInsets(cell: TableCellNode) { | ||
| function $calculateCellHorizontalInsets(cell: TableCellNode) { |
There was a problem hiding this comment.
I was thinking of exporting this, and $getCellWidth, so that a similar pattern could be used for things like ImageNodes (basically, any node that can be resized)?
There was a problem hiding this comment.
Adding exports is fine as long as the functions are suitable for being maintained as public API, or marked as @internal
There was a problem hiding this comment.
Updated to expose $getCellWidth. This specific function ($calculateCellHorizontalInsets) is now a user-specified callback and no longer needs to be exported.
|
Haven’t looked at the code but node transforms run before the DOM is updated so layout can’t be (correctly) calculated at that time. At best you can read the previously rendered DOM, but there are some big edge cases when you are working with a different version of the document. |
|
I've gone ahead and added a property to the extension I don't love that you need to provide both properties for this to work, so it might make sense to pull this out to another plugin. |
|
The edge cases are basically that subsequent versions of the lexical document can have completely arbitrary changes from one to the next. Cells could be moved to different rows or resized, but if you're trying to measure their layout from a transform you're going to either get nothing or whatever the metrics were from the last version. In many cases this could be fine, but in cases where something happens that would affect the metrics of the cell after the new version is rendered you're going to have a stale read that wouldn't be fixed up until some future update that happens to trigger a transform of the same node. If I were designing something like this I would probably use a mutation and/or update listener to handle it and maybe see if I could do most of it with direct DOM manipulation and not pushing the state back into the nodes (this kind of mechanism would be more responsive, since not all devices would necessarily measure things the same way). If not, then a cascading update to do that state update with history-merge or something like that (only if something actually needs the extra update cycle). Possibly some hybrid of the two approaches where the DOM updates are done eagerly and the render of the cascading update is mostly a no-op. |
e76d776 to
475faf3
Compare
|
@etrepum Cool idea with direct DOM manipulation. Updated the PR accordingly (triggered by a mutation listener). One effect of this change is that, since the underlying colWidths are not modified, if you shrink then restore a parent cell, the inner table reverts to its original size. Screen.Recording.2026-03-03.at.5.01.50.pm.movI also made it measure widths against the nearest root or shadow root, rather than just the nearest table cell. This makes tables also refit themselves inside things like the collapsible containers or column layouts in the Playground. In effect, that means maybe this feature is more aptly named Screen.Recording.2026-03-03.at.5.02.46.pm.mov |
etrepum
left a comment
There was a problem hiding this comment.
Small runtime compat issue that needs to be sorted but otherwise the code looks good and it works well in my testing at https://lexical-playground-2vjr0b74e-fbopensource.vercel.app/?hasNestedTables=true&tableHorizontalScroll=false&hasFitNestedTables=true


Description
#8097 implemented nested table fitting when inserting tables. However, beyond the initial insertion, it didn't handle the nested table itself changing width (1), or the surrounding cell changing width (2).
This PR changes the original implementation to a Node Transform, which handles (1).
To handle (2), the simplest approach is to mark all child tables as dirty when a column resize event occurs, so that the transform fires. I tried to do this with a Transform as well, but had issues getting it to terminate. Open to alternative ideas.
Test plan
Before
Screen.Recording.2026-02-27.at.6.16.29.pm.mov
After
Screen.Recording.2026-02-27.at.6.10.55.pm.mov