[lexical-table] Feature: add config for opting in to nested tables#7983
[lexical-table] Feature: add config for opting in to nested tables#7983etrepum merged 4 commits intofacebook:mainfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| if (selection === null) { | ||
| throw new Error('Expected valid selection'); | ||
| } | ||
| editor.dispatchCommand(SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, { |
There was a problem hiding this comment.
This wasn't actually testing anything before: verified by removing the command handler and the test still passed. We need to instead use $insertGeneratedNodes which only progresses if all the handlers for SELECTION_INSERT_CLIPBOARD_NODES_COMMAND return false.
| const extension = getExtensionDependencyFromEditor(editor, TableExtension); | ||
| extension.output.hasNestedTables.value = true; |
There was a problem hiding this comment.
@etrepum I couldn't find any examples in the codebase where extension config was being updated after-the-fact. Let me know if this isn't the right way to go about it.
There was a problem hiding this comment.
When output properties are signals they're intended to be mutable after the fact, doing it this way is fine. It's a little awkward because this would normally just be configured up front, but it is a sort of partial test that the signal is wired up correctly.
| editor.update( | ||
| () => { | ||
| const root = $getRoot().clear(); | ||
| const table = $createTableNode(); | ||
| const row = $createTableRowNode(); | ||
| const cell = $createTableCellNode(); | ||
| const paragraph = $createParagraphNode(); | ||
| cell.append(paragraph); | ||
| row.append(cell); | ||
| table.append(row); | ||
| root.append(table); | ||
| paragraph.select(); | ||
| }, | ||
| {discrete: true}, | ||
| ); |
There was a problem hiding this comment.
Switched from async to discrete: true, and added a paragraph inside the cell (otherwise $insertGeneratedNodes throws). Test is otherwise the same as it was before.
| root.append(table); | ||
| cell.select(); | ||
| }); | ||
| it('Prevents nested tables by default', async () => { |
There was a problem hiding this comment.
Github is struggling a bit with this diff. Recommend reviewing commits individually and with whitespace hidden.
| }); | ||
| } | ||
|
|
||
| export function registerPreventNestedTablesHandlers( |
There was a problem hiding this comment.
This might be better named as just registerPreventNestedTables. Open to suggestions.
There was a problem hiding this comment.
For the INSERT_TABLE_COMMAND handler this could also be implemented by passing the signal through to the insertTableCommandListener so that it can peek() the current value, which would prevent the need for registering a separate command listener at a higher priority to check this condition
| isCollab, | ||
| }) => { | ||
| test.skip(isPlainText); | ||
| await initialize({hasNestedTables: true, isCollab, page}); |
There was a problem hiding this comment.
Same as the tests removed in #7192 but with hasNestedTables: true added.
etrepum
left a comment
There was a problem hiding this comment.
This looks fine, I don't see a good reason to support this experiment in both the extension and the plugin but I don't think that's a blocker just more busywork
| // Prevent nested tables being inserted when the feature isn't enabled | ||
| useEffect(() => { | ||
| if (!hasNestedTables) { | ||
| return registerPreventNestedTablesHandlers(editor); | ||
| } | ||
| }, [editor, hasNestedTables]); | ||
|
|
There was a problem hiding this comment.
This might be a good opportunity to just stop adding features to the react plugin and only support it in the extension
There was a problem hiding this comment.
I took a stab at this but I think it'd require a large refactor of the playground App/Editor components. We'd have to replace TablePlugin with TableExtension, and I wasn't sure how to properly update the extension's config based on the values from useSettings.
I've switched to using signals for registerTablePlugin though, which avoids having to add a new registerPreventNestedTablesHandlers function.
There was a problem hiding this comment.
Basically the same way you did in the test should work, from a useEffect to control the timing. Not a big deal either way
| editor.getEditorState().read(() => { | ||
| const root = $getRoot(); | ||
| const table = root.getFirstChild(); | ||
| if (!$isTableNode(table)) { |
There was a problem hiding this comment.
not that we are using vitest you can use its assert to do this sort of thing in a more concise way
packages/lexical-table/src/index.ts
Outdated
| export type {TableDOMCell} from './LexicalTableObserver'; | ||
| export {$getTableAndElementByKey, TableObserver} from './LexicalTableObserver'; | ||
| export { | ||
| registerPreventNestedTablesHandlers, |
There was a problem hiding this comment.
If we only support this feature in the extension we could not export this function at all and then its name wouldn't matter
| }); | ||
| } | ||
|
|
||
| export function registerPreventNestedTablesHandlers( |
There was a problem hiding this comment.
For the INSERT_TABLE_COMMAND handler this could also be implemented by passing the signal through to the insertTableCommandListener so that it can peek() the current value, which would prevent the need for registering a separate command listener at a higher priority to check this condition
Description
#7192 made changes to try and prevent nested tables. They weren't removed from the document tree however, and could still be inserted when not using commands. @zurfyx also advised that nested tables are wanted at Meta, even if they're not fully supported (we also want to be able to use them).
This PR adds a config option to the plugin/extension allowing developers to opt in to allowing nested tables.
Note: there are no fixes/improvements for nested tables included (eg: #7154 is still an issue). The config option is marked
@experimentalto convey that nested tables are not properly supported.