Skip to content

Commit a2b89e9

Browse files
chore: Memoize Floating UI options in TableHandlesController (#2222)
* Memoized Floating UI options in `TableHandlesController` * Fixed extend button positions not updating when dragging in some cases
1 parent ed65123 commit a2b89e9

File tree

1 file changed

+142
-112
lines changed

1 file changed

+142
-112
lines changed

packages/react/src/components/TableHandles/TableHandlesController.tsx

Lines changed: 142 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { FC, useMemo, useState } from "react";
1212
import { offset, size } from "@floating-ui/react";
1313
import { useBlockNoteEditor } from "../../hooks/useBlockNoteEditor.js";
1414
import { useExtensionState } from "../../hooks/useExtension.js";
15+
import { FloatingUIOptions } from "../Popovers/FloatingUIOptions.js";
1516
import {
1617
GenericPopover,
1718
GenericPopoverReference,
@@ -44,25 +45,20 @@ export const TableHandlesController = <
4445

4546
const state = useExtensionState(TableHandlesExtension);
4647

47-
const references = useMemo<
48-
| {
49-
tableReference: undefined;
50-
cellReference: undefined;
51-
rowReference: undefined;
52-
columnReference: undefined;
53-
}
54-
| {
55-
tableReference: GenericPopoverReference;
56-
cellReference: GenericPopoverReference;
57-
rowReference: GenericPopoverReference;
58-
columnReference: GenericPopoverReference;
59-
}
60-
>(() => {
61-
if (
62-
state === undefined ||
63-
state.rowIndex === undefined ||
64-
state.colIndex === undefined
65-
) {
48+
const references = useMemo<{
49+
tableReference?: GenericPopoverReference;
50+
cellReference?: GenericPopoverReference;
51+
rowReference?: GenericPopoverReference;
52+
columnReference?: GenericPopoverReference;
53+
}>(() => {
54+
const references: {
55+
tableReference?: GenericPopoverReference;
56+
cellReference?: GenericPopoverReference;
57+
rowReference?: GenericPopoverReference;
58+
columnReference?: GenericPopoverReference;
59+
} = {};
60+
61+
if (state === undefined) {
6662
return {};
6763
}
6864

@@ -84,7 +80,11 @@ export const TableHandlesController = <
8480
return {};
8581
}
8682

87-
const tableReference = { element: tableElement };
83+
references.tableReference = { element: tableElement };
84+
85+
if (state.rowIndex === undefined || state.colIndex === undefined) {
86+
return references;
87+
}
8888

8989
const rowBeforePos = editor.prosemirrorState.doc
9090
.resolve(tableBeforePos + 1)
@@ -98,9 +98,8 @@ export const TableHandlesController = <
9898
return {};
9999
}
100100

101-
const cellReference = { element: cellElement };
102-
103-
const rowReference = {
101+
references.cellReference = { element: cellElement };
102+
references.rowReference = {
104103
element: tableElement,
105104
getBoundingClientRect: () => {
106105
const tableBoundingRect = tableElement.getBoundingClientRect();
@@ -117,7 +116,7 @@ export const TableHandlesController = <
117116
);
118117
},
119118
};
120-
const columnReference = {
119+
references.columnReference = {
121120
element: tableElement,
122121
getBoundingClientRect: () => {
123122
const tableBoundingRect = tableElement.getBoundingClientRect();
@@ -135,14 +134,122 @@ export const TableHandlesController = <
135134
},
136135
};
137136

138-
return {
139-
tableReference,
140-
cellReference,
141-
rowReference,
142-
columnReference,
143-
};
137+
return references;
144138
}, [editor, state]);
145139

140+
const floatingUIOptions = useMemo<
141+
| {
142+
rowTableHandle: FloatingUIOptions;
143+
columnTableHandle: FloatingUIOptions;
144+
tableCellHandle: FloatingUIOptions;
145+
extendRowsButton: FloatingUIOptions;
146+
extendColumnsButton: FloatingUIOptions;
147+
}
148+
| undefined
149+
>(
150+
() =>
151+
state !== undefined
152+
? {
153+
rowTableHandle: {
154+
useFloatingOptions: {
155+
open:
156+
state.show &&
157+
state.rowIndex !== undefined &&
158+
(!onlyShownElement || onlyShownElement === "rowTableHandle"),
159+
placement: "left",
160+
middleware: [offset(-10)],
161+
},
162+
elementProps: {
163+
style: {
164+
zIndex: 10,
165+
},
166+
},
167+
},
168+
columnTableHandle: {
169+
useFloatingOptions: {
170+
open:
171+
state.show &&
172+
state.colIndex !== undefined &&
173+
(!onlyShownElement ||
174+
onlyShownElement === "columnTableHandle"),
175+
placement: "top",
176+
middleware: [offset(-12)],
177+
},
178+
elementProps: {
179+
style: {
180+
zIndex: 10,
181+
},
182+
},
183+
},
184+
tableCellHandle: {
185+
useFloatingOptions: {
186+
open:
187+
state.show &&
188+
state.rowIndex !== undefined &&
189+
state.colIndex !== undefined &&
190+
(!onlyShownElement || onlyShownElement === "tableCellHandle"),
191+
placement: "top-end",
192+
middleware: [offset({ mainAxis: -15, crossAxis: -1 })],
193+
},
194+
elementProps: {
195+
style: {
196+
zIndex: 10,
197+
},
198+
},
199+
},
200+
extendRowsButton: {
201+
useFloatingOptions: {
202+
open:
203+
state.show &&
204+
state.showAddOrRemoveRowsButton &&
205+
(!onlyShownElement ||
206+
onlyShownElement === "extendRowsButton"),
207+
placement: "bottom",
208+
middleware: [
209+
size({
210+
apply({ rects, elements }) {
211+
Object.assign(elements.floating.style, {
212+
width: `${rects.reference.width}px`,
213+
});
214+
},
215+
}),
216+
],
217+
},
218+
elementProps: {
219+
style: {
220+
zIndex: 10,
221+
},
222+
},
223+
},
224+
extendColumnsButton: {
225+
useFloatingOptions: {
226+
open:
227+
state.show &&
228+
state.showAddOrRemoveColumnsButton &&
229+
(!onlyShownElement ||
230+
onlyShownElement === "extendColumnsButton"),
231+
placement: "right",
232+
middleware: [
233+
size({
234+
apply({ rects, elements }) {
235+
Object.assign(elements.floating.style, {
236+
height: `${rects.reference.height}px`,
237+
});
238+
},
239+
}),
240+
],
241+
},
242+
elementProps: {
243+
style: {
244+
zIndex: 10,
245+
},
246+
},
247+
},
248+
}
249+
: undefined,
250+
[onlyShownElement, state],
251+
);
252+
146253
if (!state) {
147254
return null;
148255
}
@@ -155,19 +262,7 @@ export const TableHandlesController = <
155262
<>
156263
<GenericPopover
157264
reference={references?.rowReference}
158-
useFloatingOptions={{
159-
open:
160-
state.show &&
161-
state.rowIndex !== undefined &&
162-
(!onlyShownElement || onlyShownElement === "rowTableHandle"),
163-
placement: "left",
164-
middleware: [offset(-10)],
165-
}}
166-
elementProps={{
167-
style: {
168-
zIndex: 10,
169-
},
170-
}}
265+
{...floatingUIOptions?.rowTableHandle}
171266
>
172267
{state.show &&
173268
state.rowIndex !== undefined &&
@@ -182,19 +277,7 @@ export const TableHandlesController = <
182277
</GenericPopover>
183278
<GenericPopover
184279
reference={references?.columnReference}
185-
useFloatingOptions={{
186-
open:
187-
state.show &&
188-
state.colIndex !== undefined &&
189-
(!onlyShownElement || onlyShownElement === "columnTableHandle"),
190-
placement: "top",
191-
middleware: [offset(-12)],
192-
}}
193-
elementProps={{
194-
style: {
195-
zIndex: 10,
196-
},
197-
}}
280+
{...floatingUIOptions?.columnTableHandle}
198281
>
199282
{state.show &&
200283
state.colIndex !== undefined &&
@@ -209,20 +292,7 @@ export const TableHandlesController = <
209292
</GenericPopover>
210293
<GenericPopover
211294
reference={references?.cellReference}
212-
useFloatingOptions={{
213-
open:
214-
state.show &&
215-
state.rowIndex !== undefined &&
216-
state.colIndex !== undefined &&
217-
(!onlyShownElement || onlyShownElement === "tableCellHandle"),
218-
placement: "top-end",
219-
middleware: [offset({ mainAxis: -15, crossAxis: -1 })],
220-
}}
221-
elementProps={{
222-
style: {
223-
zIndex: 10,
224-
},
225-
}}
295+
{...floatingUIOptions?.tableCellHandle}
226296
>
227297
{state.show &&
228298
state.rowIndex !== undefined &&
@@ -237,27 +307,7 @@ export const TableHandlesController = <
237307
</GenericPopover>
238308
<GenericPopover
239309
reference={references?.tableReference}
240-
useFloatingOptions={{
241-
open:
242-
state.show &&
243-
state.showAddOrRemoveRowsButton &&
244-
(!onlyShownElement || onlyShownElement === "extendRowsButton"),
245-
placement: "bottom",
246-
middleware: [
247-
size({
248-
apply({ rects, elements }) {
249-
Object.assign(elements.floating.style, {
250-
width: `${rects.reference.width}px`,
251-
});
252-
},
253-
}),
254-
],
255-
}}
256-
elementProps={{
257-
style: {
258-
zIndex: 10,
259-
},
260-
}}
310+
{...floatingUIOptions?.extendRowsButton}
261311
>
262312
{state.show &&
263313
state.showAddOrRemoveRowsButton &&
@@ -272,27 +322,7 @@ export const TableHandlesController = <
272322
</GenericPopover>
273323
<GenericPopover
274324
reference={references?.tableReference}
275-
useFloatingOptions={{
276-
open:
277-
state.show &&
278-
state.showAddOrRemoveColumnsButton &&
279-
(!onlyShownElement || onlyShownElement === "extendColumnsButton"),
280-
placement: "right",
281-
middleware: [
282-
size({
283-
apply({ rects, elements }) {
284-
Object.assign(elements.floating.style, {
285-
height: `${rects.reference.height}px`,
286-
});
287-
},
288-
}),
289-
],
290-
}}
291-
elementProps={{
292-
style: {
293-
zIndex: 10,
294-
},
295-
}}
325+
{...floatingUIOptions?.extendColumnsButton}
296326
>
297327
{state.show &&
298328
state.showAddOrRemoveColumnsButton &&

0 commit comments

Comments
 (0)