Skip to content

Commit

Permalink
Implemented PR feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewlipski committed Oct 23, 2024
1 parent 41fa26f commit cfb0168
Show file tree
Hide file tree
Showing 12 changed files with 190 additions and 167 deletions.
6 changes: 1 addition & 5 deletions packages/core/src/api/nodeConversions/blockToNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,7 @@ export function tableContentToNodes<
// The colwidth array should have multiple values when the colspan of
// a cell is greater than 1. However, this is not yet implemented so
// we can always assume a length of 1.
colwidth: [
tableContent.columnWidths
? tableContent.columnWidths[i] || 100
: 100,
],
colwidth: [tableContent.columnWidths?.[i] || null],
},
pNode
);
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/api/nodeConversions/nodeToBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export function contentNodeToTableContent<
// The colwidth array should have multiple values when the colspan of a
// cell is greater than 1. However, this is not yet implemented so we
// can always assume a length of 1.
ret.columnWidths.push(cellNode.attrs.colwidth[0] || 100);
ret.columnWidths.push(cellNode.attrs.colwidth[0] || undefined);
});
}

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/editor/editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ Tippy popups that are appended to document.body directly

/* table related: */
.bn-editor table {
/* TODO: Do we want this? */
width: auto !important;
margin-bottom: 2em;
}
Expand Down
25 changes: 19 additions & 6 deletions packages/core/src/extensions/TableHandles/TableHandlesPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Plugin, PluginKey, PluginView } from "prosemirror-state";
import { Decoration, DecorationSet, EditorView } from "prosemirror-view";
import { nodeToBlock } from "../../api/nodeConversions/nodeToBlock.js";
import { checkBlockIsDefaultType } from "../../blocks/defaultBlockTypeGuards.js";
import { Block, DefaultBlockSchema } from "../../blocks/defaultBlocks.js";
import { DefaultBlockSchema } from "../../blocks/defaultBlocks.js";
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";
import {
BlockFromConfigNoChildren,
Expand All @@ -20,6 +20,8 @@ export type TableHandlesState<
S extends StyleSchema
> = {
show: boolean;
showExtendButtonRow: boolean;
showExtendButtonCol: boolean;
referencePosCell: DOMRect;
referencePosTable: DOMRect;

Expand Down Expand Up @@ -164,6 +166,8 @@ export class TableHandlesView<

if (this.state?.show) {
this.state.show = false;
this.state.showExtendButtonRow = false;
this.state.showExtendButtonCol = false;
this.emitUpdate();
}
}
Expand All @@ -177,6 +181,8 @@ export class TableHandlesView<
if (!target || !this.editor.isEditable) {
if (this.state?.show) {
this.state.show = false;
this.state.showExtendButtonRow = false;
this.state.showExtendButtonCol = false;
this.emitUpdate();
}
return;
Expand All @@ -198,7 +204,9 @@ export class TableHandlesView<
}
this.tableElement = blockEl.node;

let tableBlock: Block<any, any, any> | undefined = undefined;
let tableBlock:
| BlockFromConfigNoChildren<DefaultBlockSchema["table"], I, S>
| undefined;

// Copied from `getBlock`. We don't use `getBlock` since we also need the PM
// node for the table, so we would effectively be doing the same work twice.
Expand Down Expand Up @@ -245,6 +253,9 @@ export class TableHandlesView<

this.state = {
show: true,
showExtendButtonRow:
colIndex === tableBlock.content.rows[0].cells.length - 1,
showExtendButtonCol: rowIndex === tableBlock.content.rows.length - 1,
referencePosCell: cellRect,
referencePosTable: tableRect,

Expand Down Expand Up @@ -418,30 +429,32 @@ export class TableHandlesView<
return;
}

// TODO: Can also just do down the DOM tree until we find it but this seems
// cleaner.
const tableBody = this.tableElement!.querySelector("tbody");
if (!tableBody) {
return;
}

// If rows or columns are deleted in the update, the hovered indices for
// those may now be out of bounds. If this is the case, they are moved to
// the new last row or column.
if (this.state.rowIndex >= tableBody.children.length) {
this.state.rowIndex = tableBody.children.length - 1;
this.emitUpdate();

return;
}
const row = tableBody.children[this.state.rowIndex];

if (this.state.colIndex >= tableBody.children[0].children.length) {
this.state.colIndex = tableBody.children[0].children.length - 1;
this.emitUpdate();

return;
}

const row = tableBody.children[this.state.rowIndex];
const cell = row.children[this.state.colIndex];

// TODO: Check if DOMRects changed first?
this.state.block = this.editor.getBlock(this.state.block.id)!;
this.state.referencePosCell = cell.getBoundingClientRect();
this.state.referencePosTable = tableBody.getBoundingClientRect();
this.emitUpdate();
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/schema/blocks/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export type TableContent<
S extends StyleSchema = StyleSchema
> = {
type: "tableContent";
columnWidths: number[];
columnWidths: (number | undefined)[];
rows: {
cells: InlineContent<I, S>[][];
}[];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import {
BlockFromConfigNoChildren,
DefaultBlockSchema,
DefaultInlineContentSchema,
DefaultStyleSchema,
InlineContentSchema,
Expand All @@ -9,6 +11,7 @@ import {
import {
MouseEvent as ReactMouseEvent,
ReactNode,
useCallback,
useEffect,
useState,
} from "react";
Expand All @@ -17,6 +20,21 @@ import { RiAddFill } from "react-icons/ri";
import { useComponentsContext } from "../../../editor/ComponentsContext.js";
import { ExtendButtonProps } from "./ExtendButtonProps.js";

// Rounds a number up or down, depending on whether the value past the decimal
// point is above or below a certain fraction. If no fraction is provided, it
// behaves like Math.round.
const roundUpAt = (num: number, fraction = 0.5) => {
if (fraction <= 0 || fraction >= 100) {
throw new Error("Percentage must be between 0 and 1");
}

if (num < fraction) {
return Math.floor(num);
}

return Math.ceil(num);
};

const getContentWithAddedRows = <
I extends InlineContentSchema,
S extends StyleSchema
Expand All @@ -34,9 +52,7 @@ const getContentWithAddedRows = <

return {
type: "tableContent",
columnWidths: content.columnWidths
? [...content.columnWidths, ...newRows.map(() => undefined)]
: undefined,
columnWidths: content.columnWidths,
rows: [...content.rows, ...newRows],
};
};
Expand All @@ -57,7 +73,9 @@ const getContentWithAddedCols = <

return {
type: "tableContent",
columnWidths: content.columnWidths || undefined,
columnWidths: content.columnWidths
? [...content.columnWidths, ...newCells.map(() => undefined)]
: undefined,
rows: content.rows.map((row) => ({
cells: [...row.cells, ...newCells],
})),
Expand All @@ -73,22 +91,23 @@ export const ExtendButton = <
const Components = useComponentsContext()!;

const [editingState, setEditingState] = useState<{
originalBlock: BlockFromConfigNoChildren<DefaultBlockSchema["table"], I, S>;
startPos: number;
numOriginalCells: number;
clickOnly: boolean;
} | null>(null);

const mouseDownHandler = (event: ReactMouseEvent) => {
props.freezeHandles();
setEditingState({
startPos: props.orientation === "row" ? event.clientX : event.clientY,
numOriginalCells:
props.orientation === "row"
? props.block.content.rows[0].cells.length
: props.block.content.rows.length,
clickOnly: true,
});
};
// Lets the user start extending columns/rows by moving the mouse.
const mouseDownHandler = useCallback(
(event: ReactMouseEvent) => {
props.freezeHandles();
setEditingState({
originalBlock: props.block,
startPos: props.orientation === "row" ? event.clientX : event.clientY,
clickOnly: true,
});
},
[props]
);

// Extends columns/rows on when moving the mouse.
useEffect(() => {
Expand All @@ -101,35 +120,36 @@ export const ExtendButton = <
(props.orientation === "row" ? event.clientX : event.clientY) -
editingState.startPos;

const numCells =
editingState.numOriginalCells +
Math.floor(diff / (props.orientation === "row" ? 100 : 31));
const block = props.editor.getBlock(props.block)!;
const numCurrentCells =
const numOriginalCells =
props.orientation === "row"
? editingState.originalBlock.content.rows[0].cells.length
: editingState.originalBlock.content.rows.length;
const oldNumCells =
props.orientation === "row"
? block.content.rows[0].cells.length
: block.content.rows.length;
? props.block.content.rows[0].cells.length
: props.block.content.rows.length;
const newNumCells =
numOriginalCells +
roundUpAt(diff / (props.orientation === "row" ? 100 : 31), 0.3);

if (
editingState.numOriginalCells <= numCells &&
numCells !== numCurrentCells
) {
if (numOriginalCells <= newNumCells && newNumCells !== oldNumCells) {
props.editor.updateBlock(props.block, {
type: "table",
content:
props.orientation === "row"
? getContentWithAddedCols(
props.block.content,
numCells - editingState.numOriginalCells
editingState.originalBlock.content,
newNumCells - numOriginalCells
)
: getContentWithAddedRows(
props.block.content,
numCells - editingState.numOriginalCells
editingState.originalBlock.content,
newNumCells - numOriginalCells
),
});

// Edge case for updating block content as `updateBlock` causes the
// selection to move into the next block, so we have to set it back.
if (block.content) {
if (editingState.originalBlock.content) {
props.editor.setTextCursorPosition(props.block);
}
setEditingState({ ...editingState, clickOnly: false });
Expand All @@ -153,8 +173,8 @@ export const ExtendButton = <
type: "table",
content:
props.orientation === "row"
? getContentWithAddedCols(props.block.content)
: getContentWithAddedRows(props.block.content),
? getContentWithAddedCols(editingState.originalBlock.content)
: getContentWithAddedRows(editingState.originalBlock.content),
});
}

Expand All @@ -167,12 +187,7 @@ export const ExtendButton = <
return () => {
document.body.removeEventListener("mouseup", callback);
};
}, [
editingState?.clickOnly,
getContentWithAddedCols,
getContentWithAddedRows,
props,
]);
}, [editingState?.clickOnly, editingState?.originalBlock.content, props]);

return (
<Components.TableHandle.ExtendButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export const AddColumnButton = <
columnWidths: props.block.content.columnWidths.toSpliced(
props.index + (props.side === "right" ? 1 : 0),
0,
100
undefined
),
rows: props.block.content.rows.map((row) => {
const cells = [...row.cells];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ export const DeleteRowButton = <
onClick={() => {
const content: PartialTableContent<I, S> = {
type: "tableContent",
columnWidths: props.block.content.columnWidths.filter(
(_, index) => index !== props.index
),
columnWidths: props.block.content.columnWidths,
rows: props.block.content.rows.filter(
(_, index) => index !== props.index
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ import {
import { FC, useMemo, useState } from "react";

import { useBlockNoteEditor } from "../../hooks/useBlockNoteEditor.js";
import {
useExtendButtonsPositioning,
useTableHandlesPositioning,
} from "./hooks/useTableHandlesPositioning.js";
import { useExtendButtonsPositioning } from "./hooks/useExtendButtonsPositioning.js";
import { useTableHandlesPositioning } from "./hooks/useTableHandlesPositioning.js";
import { useUIPluginState } from "../../hooks/useUIPluginState.js";
import { ExtendButton } from "./ExtendButton/ExtendButton.js";
import { TableHandle } from "./TableHandle.js";
Expand Down Expand Up @@ -71,7 +69,8 @@ export const TableHandlesController = <
);

const { rowExtendButton, colExtendButton } = useExtendButtonsPositioning(
state?.show || false,
state?.showExtendButtonRow || false,
state?.showExtendButtonCol || false,
state?.referencePosCell || null,
state?.referencePosTable || null,
draggingState
Expand Down
Loading

0 comments on commit cfb0168

Please sign in to comment.