diff --git a/packages/core/src/blocks/Table/block.ts b/packages/core/src/blocks/Table/block.ts index 9a23d227aa..c71d9ffb7d 100644 --- a/packages/core/src/blocks/Table/block.ts +++ b/packages/core/src/blocks/Table/block.ts @@ -10,6 +10,7 @@ import { TableContent, } from "../../schema/index.js"; import { mergeCSSClasses } from "../../util/browser.js"; +import { camelToDataKebab } from "../../util/string.js"; import { createDefaultBlockDOMOutputSpec } from "../defaultBlockHelpers.js"; import { defaultProps } from "../defaultProps.js"; import { EMPTY_CELL_WIDTH, TableExtension } from "./TableExtension.js"; @@ -252,6 +253,31 @@ const TiptapTableNode = Node.create({ super.ignoreMutation(record) ); } + + // `TableView` implements its own `update` method, as the view needs to + // be persisted across updates for column resizing to work properly. + // However, it doesn't do anything else, so we have to re-apply the + // HTML attributes from props manually. This isn't an issue for node + // views created e.g. by custom blocks, as those aren't persisted + // across updates (they are reinstantiated each time), and so + // `HTMLAttributes` is always up-to-date for those. + update(updatedNode: PMNode): boolean { + if (!super.update(updatedNode)) { + return false; + } + + for (const [propName, propSpec] of Object.entries(tablePropSchema)) { + const attrName = camelToDataKebab(propName); + const value = updatedNode.attrs[propName]; + if (value !== propSpec.default) { + this.dom.setAttribute(attrName, String(value)); + } else { + this.dom.removeAttribute(attrName); + } + } + + return true; + } } return new BlockNoteTableView(node, EMPTY_CELL_WIDTH, { diff --git a/tests/src/end-to-end/colors/colors.test.ts b/tests/src/end-to-end/colors/colors.test.ts index 7751a72cf9..6c8f00f2b7 100644 --- a/tests/src/end-to-end/colors/colors.test.ts +++ b/tests/src/end-to-end/colors/colors.test.ts @@ -7,10 +7,12 @@ import { DRAG_HANDLE_MENU_SELECTOR, DRAG_HANDLE_SELECTOR, H_TWO_BLOCK_SELECTOR, + TABLE_SELECTOR, TEXT_COLOR_SELECTOR, } from "../../utils/const.js"; import { insertHeading, insertParagraph } from "../../utils/copypaste.js"; import { focusOnEditor } from "../../utils/editor.js"; +import { executeSlashCommand } from "../../utils/slashmenu.js"; test.beforeEach(async ({ page }) => { await page.goto(BASE_URL, { waitUntil: "networkidle" }); @@ -109,4 +111,26 @@ test.describe("Check Background & Text Color Functionality", () => { expect(await page.screenshot()).toMatchSnapshot("blockBackgroundColor.png"); }); + // Regression test: prosemirror-tables' TableView.update() preserves the + // NodeView's DOM without re-applying node attrs, so prop changes (e.g. + // textColor) wouldn't propagate to the blockContent wrapper. BlockNoteTableView + // overrides update() to sync prop-derived data-* attributes. + test("Should be able to set block text color on a table", async ({ + page, + }) => { + await focusOnEditor(page); + await executeSlashCommand(page, "table"); + await page.keyboard.type("Table Cell"); + + await page.hover(TABLE_SELECTOR); + await page.click(DRAG_HANDLE_SELECTOR); + await page.waitForSelector(DRAG_HANDLE_MENU_SELECTOR); + await page.hover("text=Colors"); + + const element = page.locator(TEXT_COLOR_SELECTOR("red")); + const boundingBox = (await element.boundingBox())!; + await page.mouse.click(boundingBox.x + 10, boundingBox.y + 10); + + expect(await page.screenshot()).toMatchSnapshot("blockTextColorTable.png"); + }); }); diff --git a/tests/src/end-to-end/colors/colors.test.ts-snapshots/blockTextColorTable-chromium-linux.png b/tests/src/end-to-end/colors/colors.test.ts-snapshots/blockTextColorTable-chromium-linux.png new file mode 100644 index 0000000000..ae74e34095 Binary files /dev/null and b/tests/src/end-to-end/colors/colors.test.ts-snapshots/blockTextColorTable-chromium-linux.png differ diff --git a/tests/src/end-to-end/colors/colors.test.ts-snapshots/blockTextColorTable-firefox-linux.png b/tests/src/end-to-end/colors/colors.test.ts-snapshots/blockTextColorTable-firefox-linux.png new file mode 100644 index 0000000000..950fd729a5 Binary files /dev/null and b/tests/src/end-to-end/colors/colors.test.ts-snapshots/blockTextColorTable-firefox-linux.png differ diff --git a/tests/src/end-to-end/colors/colors.test.ts-snapshots/blockTextColorTable-webkit-linux.png b/tests/src/end-to-end/colors/colors.test.ts-snapshots/blockTextColorTable-webkit-linux.png new file mode 100644 index 0000000000..e9dec2867c Binary files /dev/null and b/tests/src/end-to-end/colors/colors.test.ts-snapshots/blockTextColorTable-webkit-linux.png differ